summaryrefslogtreecommitdiff
path: root/svx/source/form
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/form')
-rw-r--r--svx/source/form/ParseContext.cxx252
-rw-r--r--svx/source/form/dataaccessdescriptor.cxx569
-rw-r--r--svx/source/form/databaselocationinput.cxx317
-rw-r--r--svx/source/form/datalistener.cxx100
-rw-r--r--svx/source/form/datanavi.cxx3727
-rw-r--r--svx/source/form/datanavi.src1148
-rw-r--r--svx/source/form/dbcharsethelper.cxx61
-rw-r--r--svx/source/form/dbtoolsclient.cxx368
-rw-r--r--svx/source/form/delayedevent.cxx71
-rw-r--r--svx/source/form/filtnav.cxx2064
-rw-r--r--svx/source/form/filtnav.src87
-rw-r--r--svx/source/form/fmPropBrw.cxx727
-rw-r--r--svx/source/form/fmcontrolbordermanager.cxx443
-rw-r--r--svx/source/form/fmcontrollayout.cxx331
-rw-r--r--svx/source/form/fmdmod.cxx134
-rw-r--r--svx/source/form/fmdocumentclassification.cxx214
-rw-r--r--svx/source/form/fmdpage.cxx148
-rw-r--r--svx/source/form/fmexch.cxx443
-rw-r--r--svx/source/form/fmexpl.cxx736
-rw-r--r--svx/source/form/fmexpl.src371
-rw-r--r--svx/source/form/fmitems.cxx71
-rw-r--r--svx/source/form/fmmodel.cxx372
-rw-r--r--svx/source/form/fmobj.cxx739
-rw-r--r--svx/source/form/fmobjfac.cxx266
-rw-r--r--svx/source/form/fmpage.cxx274
-rw-r--r--svx/source/form/fmpgeimp.cxx742
-rw-r--r--svx/source/form/fmscriptingenv.cxx579
-rw-r--r--svx/source/form/fmservs.cxx109
-rw-r--r--svx/source/form/fmshell.cxx1513
-rw-r--r--svx/source/form/fmshimp.cxx4340
-rw-r--r--svx/source/form/fmsrccfg.cxx321
-rw-r--r--svx/source/form/fmsrcimp.cxx1300
-rw-r--r--svx/source/form/fmstring.src491
-rw-r--r--svx/source/form/fmtextcontroldialogs.cxx122
-rw-r--r--svx/source/form/fmtextcontrolfeature.cxx133
-rw-r--r--svx/source/form/fmtextcontrolshell.cxx1401
-rw-r--r--svx/source/form/fmtools.cxx498
-rw-r--r--svx/source/form/fmundo.cxx1350
-rw-r--r--svx/source/form/fmview.cxx628
-rw-r--r--svx/source/form/fmvwimp.cxx1961
-rw-r--r--svx/source/form/formcontrolfactory.cxx736
-rw-r--r--svx/source/form/formcontroller.cxx4320
-rw-r--r--svx/source/form/formcontrolling.cxx608
-rw-r--r--svx/source/form/formdispatchinterceptor.cxx217
-rw-r--r--svx/source/form/formfeaturedispatcher.cxx244
-rw-r--r--svx/source/form/formshell.src227
-rw-r--r--svx/source/form/formtoolbars.cxx117
-rw-r--r--svx/source/form/legacyformcontroller.cxx228
-rw-r--r--svx/source/form/makefile.mk123
-rw-r--r--svx/source/form/navigatortree.cxx2301
-rw-r--r--svx/source/form/navigatortreemodel.cxx1120
-rw-r--r--svx/source/form/sdbdatacolumn.cxx290
-rw-r--r--svx/source/form/sqlparserclient.cxx64
-rw-r--r--svx/source/form/stringlistresource.cxx74
-rw-r--r--svx/source/form/tabwin.cxx470
-rw-r--r--svx/source/form/tbxform.cxx469
-rw-r--r--svx/source/form/typeconversionclient.cxx60
-rw-r--r--svx/source/form/typemap.cxx63
-rw-r--r--svx/source/form/xfm_addcondition.cxx193
59 files changed, 41445 insertions, 0 deletions
diff --git a/svx/source/form/ParseContext.cxx b/svx/source/form/ParseContext.cxx
new file mode 100644
index 000000000000..b92f39caa6d1
--- /dev/null
+++ b/svx/source/form/ParseContext.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+#include "ParseContext.hxx"
+#include "stringlistresource.hxx"
+#include "fmresids.hrc"
+
+#include <svx/dialmgr.hxx>
+
+#include <unotools/syslocale.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/debug.hxx>
+#include <osl/mutex.hxx>
+
+using namespace svxform;
+using namespace ::connectivity;
+//==========================================================================
+//= OSystemParseContext
+//==========================================================================
+DBG_NAME(OSystemParseContext)
+//-----------------------------------------------------------------------------
+OSystemParseContext::OSystemParseContext() : IParseContext()
+{
+ DBG_CTOR(OSystemParseContext,NULL);
+ SolarMutexGuard aGuard;
+
+ ::svx::StringListResource aKeywords( SVX_RES( RID_RSC_SQL_INTERNATIONAL ) );
+ aKeywords.get( m_aLocalizedKeywords );
+}
+
+//-----------------------------------------------------------------------------
+OSystemParseContext::~OSystemParseContext()
+{
+ DBG_DTOR(OSystemParseContext,NULL);
+}
+
+//-----------------------------------------------------------------------------
+::com::sun::star::lang::Locale OSystemParseContext::getPreferredLocale( ) const
+{
+ return SvtSysLocale().GetLocaleData().getLocale();
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OUString OSystemParseContext::getErrorMessage(ErrorCode _eCode) const
+{
+ String aMsg;
+ SolarMutexGuard aGuard;
+ switch (_eCode)
+ {
+ case ERROR_GENERAL: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_ERROR); break;
+ case ERROR_VALUE_NO_LIKE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_VALUE_NO_LIKE); break;
+ case ERROR_FIELD_NO_LIKE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_FIELD_NO_LIKE); break;
+ case ERROR_INVALID_COMPARE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_CRIT_NO_COMPARE); break;
+ case ERROR_INVALID_INT_COMPARE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_INT_NO_VALID); break;
+ case ERROR_INVALID_DATE_COMPARE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_ACCESS_DAT_NO_VALID); break;
+ case ERROR_INVALID_REAL_COMPARE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_REAL_NO_VALID); break;
+ case ERROR_INVALID_TABLE: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_TABLE); break;
+ case ERROR_INVALID_TABLE_OR_QUERY: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_TABLE_OR_QUERY); break;
+ case ERROR_INVALID_COLUMN: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_COLUMN); break;
+ case ERROR_INVALID_TABLE_EXIST: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_TABLE_EXISTS); break;
+ case ERROR_INVALID_QUERY_EXIST: aMsg = SVX_RES(RID_STR_SVT_SQL_SYNTAX_QUERY_EXISTS); break;
+ case ERROR_NONE: break;
+ }
+ return aMsg;
+}
+
+//-----------------------------------------------------------------------------
+::rtl::OString OSystemParseContext::getIntlKeywordAscii(InternationalKeyCode _eKey) const
+{
+ size_t nIndex = 0;
+ switch ( _eKey )
+ {
+ case KEY_LIKE: nIndex = 0; break;
+ case KEY_NOT: nIndex = 1; break;
+ case KEY_NULL: nIndex = 2; break;
+ case KEY_TRUE: nIndex = 3; break;
+ case KEY_FALSE: nIndex = 4; break;
+ case KEY_IS: nIndex = 5; break;
+ case KEY_BETWEEN: nIndex = 6; break;
+ case KEY_OR: nIndex = 7; break;
+ case KEY_AND: nIndex = 8; break;
+ case KEY_AVG: nIndex = 9; break;
+ case KEY_COUNT: nIndex = 10; break;
+ case KEY_MAX: nIndex = 11; break;
+ case KEY_MIN: nIndex = 12; break;
+ case KEY_SUM: nIndex = 13; break;
+ case KEY_EVERY: nIndex = 14; break;
+ case KEY_ANY: nIndex = 15; break;
+ case KEY_SOME: nIndex = 16; break;
+ case KEY_STDDEV_POP: nIndex = 17; break;
+ case KEY_STDDEV_SAMP: nIndex = 18; break;
+ case KEY_VAR_SAMP: nIndex = 19; break;
+ case KEY_VAR_POP: nIndex = 20; break;
+ case KEY_COLLECT: nIndex = 21; break;
+ case KEY_FUSION: nIndex = 22; break;
+ case KEY_INTERSECTION: nIndex = 23; break;
+ case KEY_NONE:
+ DBG_ERROR( "OSystemParseContext::getIntlKeywordAscii: illegal argument!" );
+ break;
+ }
+
+ OSL_ENSURE( nIndex < m_aLocalizedKeywords.size(), "OSystemParseContext::getIntlKeywordAscii: invalid index!" );
+
+ ByteString sKeyword;
+ if ( nIndex < m_aLocalizedKeywords.size() )
+ sKeyword = ByteString( m_aLocalizedKeywords[nIndex], RTL_TEXTENCODING_UTF8 );
+ return sKeyword;
+}
+
+//-----------------------------------------------------------------------------
+static sal_Unicode lcl_getSeparatorChar( const String& _rSeparator, sal_Unicode _nFallback )
+{
+ DBG_ASSERT( 0 < _rSeparator.Len(), "::lcl_getSeparatorChar: invalid decimal separator!" );
+
+ sal_Unicode nReturn( _nFallback );
+ if ( _rSeparator.Len() )
+ nReturn = static_cast< sal_Char >( _rSeparator.GetBuffer( )[0] );
+ return nReturn;
+}
+
+//-----------------------------------------------------------------------------
+sal_Unicode OSystemParseContext::getNumDecimalSep( ) const
+{
+ return lcl_getSeparatorChar( SvtSysLocale().GetLocaleData().getNumDecimalSep(), '.' );
+}
+
+//-----------------------------------------------------------------------------
+sal_Unicode OSystemParseContext::getNumThousandSep( ) const
+{
+ return lcl_getSeparatorChar( SvtSysLocale().GetLocaleData().getNumThousandSep(), ',' );
+}
+// -----------------------------------------------------------------------------
+IParseContext::InternationalKeyCode OSystemParseContext::getIntlKeyCode(const ::rtl::OString& rToken) const
+{
+ static IParseContext::InternationalKeyCode Intl_TokenID[] =
+ {
+ KEY_LIKE, KEY_NOT, KEY_NULL, KEY_TRUE,
+ KEY_FALSE, KEY_IS, KEY_BETWEEN, KEY_OR,
+ KEY_AND, KEY_AVG, KEY_COUNT, KEY_MAX,
+ KEY_MIN, KEY_SUM, KEY_EVERY,
+ KEY_ANY, KEY_SOME, KEY_STDDEV_POP,
+ KEY_STDDEV_SAMP, KEY_VAR_SAMP, KEY_VAR_POP,
+ KEY_COLLECT, KEY_FUSION, KEY_INTERSECTION
+ };
+
+ sal_uInt32 nCount = SAL_N_ELEMENTS( Intl_TokenID );
+ for (sal_uInt32 i = 0; i < nCount; i++)
+ {
+ ::rtl::OString aKey = getIntlKeywordAscii(Intl_TokenID[i]);
+ if (rToken.equalsIgnoreAsciiCase(aKey))
+ return Intl_TokenID[i];
+ }
+
+ return KEY_NONE;
+}
+
+
+// =============================================================================
+// =============================================================================
+namespace
+{
+ // -----------------------------------------------------------------------------
+ ::osl::Mutex& getSafteyMutex()
+ {
+ static ::osl::Mutex s_aSafety;
+ return s_aSafety;
+ }
+ // -----------------------------------------------------------------------------
+ oslInterlockedCount& getCounter()
+ {
+ static oslInterlockedCount s_nCounter;
+ return s_nCounter;
+ }
+ // -----------------------------------------------------------------------------
+ OSystemParseContext* getSharedContext(OSystemParseContext* _pContext = NULL,sal_Bool _bSet = sal_False)
+ {
+ static OSystemParseContext* s_pSharedContext = NULL;
+ if ( _pContext && !s_pSharedContext )
+ {
+ s_pSharedContext = _pContext;
+ return s_pSharedContext;
+ }
+ if ( _bSet )
+ {
+ OSystemParseContext* pReturn = _pContext ? _pContext : s_pSharedContext;
+ s_pSharedContext = _pContext;
+ return pReturn;
+ }
+ return s_pSharedContext;
+ }
+ // -----------------------------------------------------------------------------
+}
+// -----------------------------------------------------------------------------
+OParseContextClient::OParseContextClient()
+{
+ ::osl::MutexGuard aGuard( getSafteyMutex() );
+ if ( 1 == osl_incrementInterlockedCount( &getCounter() ) )
+ { // first instance
+ getSharedContext( new OSystemParseContext );
+ }
+}
+
+// -----------------------------------------------------------------------------
+OParseContextClient::~OParseContextClient()
+{
+ {
+ ::osl::MutexGuard aGuard( getSafteyMutex() );
+ if ( 0 == osl_decrementInterlockedCount( &getCounter() ) )
+ delete getSharedContext(NULL,sal_True);
+ }
+}
+// -----------------------------------------------------------------------------
+const OSystemParseContext* OParseContextClient::getParseContext() const
+{
+ return getSharedContext();
+}
+// -----------------------------------------------------------------------------
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/dataaccessdescriptor.cxx b/svx/source/form/dataaccessdescriptor.cxx
new file mode 100644
index 000000000000..575481527996
--- /dev/null
+++ b/svx/source/form/dataaccessdescriptor.cxx
@@ -0,0 +1,569 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/dataaccessdescriptor.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <tools/urlobj.hxx>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::comphelper;
+
+#define CONST_CHAR( propname ) propname, sizeof(propname) - 1
+
+#ifndef SVX_LIGHT
+ //====================================================================
+ //= ODADescriptorImpl
+ //====================================================================
+ class ODADescriptorImpl
+ {
+ protected:
+ sal_Bool m_bSetOutOfDate : 1;
+ sal_Bool m_bSequenceOutOfDate : 1;
+
+ public:
+ typedef ::std::map< DataAccessDescriptorProperty, Any > DescriptorValues;
+ DescriptorValues m_aValues;
+ Sequence< PropertyValue > m_aAsSequence;
+ Reference< XPropertySet > m_xAsSet;
+
+ typedef ::std::map< ::rtl::OUString, PropertyMapEntry* > MapString2PropertyEntry;
+
+ public:
+ ODADescriptorImpl();
+ ODADescriptorImpl(const ODADescriptorImpl& _rSource);
+
+ void invalidateExternRepresentations();
+
+ void updateSequence();
+ void updateSet();
+
+ /** builds the descriptor from a property value sequence
+ @return <TRUE/>
+ if and only if the sequence contained valid properties only
+ */
+ sal_Bool buildFrom( const Sequence< PropertyValue >& _rValues );
+
+ /** builds the descriptor from a property set
+ @return <TRUE/>
+ if and only if the set contained valid properties only
+ */
+ sal_Bool buildFrom( const Reference< XPropertySet >& _rValues );
+
+ protected:
+ static PropertyValue buildPropertyValue( const DescriptorValues::const_iterator& _rPos );
+ static const MapString2PropertyEntry& getPropertyMap( );
+ static PropertyMapEntry* getPropertyMapEntry( const DescriptorValues::const_iterator& _rPos );
+ };
+
+ //--------------------------------------------------------------------
+ ODADescriptorImpl::ODADescriptorImpl()
+ :m_bSetOutOfDate(sal_True)
+ ,m_bSequenceOutOfDate(sal_True)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ ODADescriptorImpl::ODADescriptorImpl(const ODADescriptorImpl& _rSource)
+ :m_bSetOutOfDate( _rSource.m_bSetOutOfDate )
+ ,m_bSequenceOutOfDate( _rSource.m_bSequenceOutOfDate )
+ ,m_aValues( _rSource.m_aValues )
+ {
+ if (!m_bSetOutOfDate)
+ m_xAsSet = _rSource.m_xAsSet;
+ if (!m_bSequenceOutOfDate)
+ m_aAsSequence = _rSource.m_aAsSequence;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool ODADescriptorImpl::buildFrom( const Sequence< PropertyValue >& _rValues )
+ {
+ const MapString2PropertyEntry& rProperties = getPropertyMap();
+
+ sal_Bool bValidPropsOnly = sal_True;
+
+ // loop through the sequence, and fill our m_aValues
+ const PropertyValue* pValues = _rValues.getConstArray();
+ const PropertyValue* pValuesEnd = pValues + _rValues.getLength();
+ for (;pValues != pValuesEnd; ++pValues)
+ {
+ MapString2PropertyEntry::const_iterator aPropPos = rProperties.find( pValues->Name );
+ if ( aPropPos != rProperties.end() )
+ {
+ DataAccessDescriptorProperty eProperty = (DataAccessDescriptorProperty)aPropPos->second->mnHandle;
+ m_aValues[eProperty] = pValues->Value;
+ }
+ else
+ // unknown property
+ bValidPropsOnly = sal_False;
+ }
+
+ if (bValidPropsOnly)
+ {
+ m_aAsSequence = _rValues;
+ m_bSequenceOutOfDate = sal_False;
+ }
+ else
+ m_bSequenceOutOfDate = sal_True;
+
+ return bValidPropsOnly;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool ODADescriptorImpl::buildFrom( const Reference< XPropertySet >& _rxValues )
+ {
+ Reference< XPropertySetInfo > xPropInfo;
+ if (_rxValues.is())
+ xPropInfo = _rxValues->getPropertySetInfo();
+ if (!xPropInfo.is())
+ {
+ OSL_ENSURE(sal_False, "ODADescriptorImpl::buildFrom: invalid property set!");
+ return sal_False;
+ }
+
+ // build a PropertyValue sequence with the current values
+ Sequence< Property > aProperties = xPropInfo->getProperties();
+ const Property* pProperty = aProperties.getConstArray();
+ const Property* pPropertyEnd = pProperty + aProperties.getLength();
+
+ Sequence< PropertyValue > aValues(aProperties.getLength());
+ PropertyValue* pValues = aValues.getArray();
+
+ for (;pProperty != pPropertyEnd; ++pProperty, ++pValues)
+ {
+ pValues->Name = pProperty->Name;
+ pValues->Value = _rxValues->getPropertyValue(pProperty->Name);
+ }
+
+ sal_Bool bValidPropsOnly = buildFrom(aValues);
+ if (bValidPropsOnly)
+ {
+ m_xAsSet = _rxValues;
+ m_bSetOutOfDate = sal_False;
+ }
+ else
+ m_bSetOutOfDate = sal_True;
+
+ return bValidPropsOnly;
+ }
+
+ //--------------------------------------------------------------------
+ void ODADescriptorImpl::invalidateExternRepresentations()
+ {
+ m_bSetOutOfDate = sal_True;
+ m_bSequenceOutOfDate = sal_True;
+ }
+
+ //--------------------------------------------------------------------
+ const ODADescriptorImpl::MapString2PropertyEntry& ODADescriptorImpl::getPropertyMap( )
+ {
+ // the properties we know
+ static MapString2PropertyEntry s_aProperties;
+ if ( s_aProperties.empty() )
+ {
+ static PropertyMapEntry s_aDesriptorProperties[] =
+ {
+ { CONST_CHAR("ActiveConnection"), daConnection, &::getCppuType( static_cast< Reference< XConnection >* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("BookmarkSelection"), daBookmarkSelection, &::getBooleanCppuType( ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Column"), daColumnObject, &::getCppuType( static_cast< Reference< XPropertySet >* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("ColumnName"), daColumnName, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Command"), daCommand, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("CommandType"), daCommandType, &::getCppuType( static_cast< sal_Int32* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Component"), daComponent, &::getCppuType( static_cast< Reference< XContent >* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("ConnectionResource"), daConnectionResource, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Cursor"), daCursor, &::getCppuType( static_cast< Reference< XResultSet>* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("DataSourceName"), daDataSource, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("DatabaseLocation"), daDatabaseLocation, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("EscapeProcessing"), daEscapeProcessing, &::getBooleanCppuType( ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Filter"), daFilter, &::getCppuType( static_cast< ::rtl::OUString* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { CONST_CHAR("Selection"), daSelection, &::getCppuType( static_cast< Sequence< Any >* >(NULL) ), PropertyAttribute::TRANSIENT, 0 },
+ { NULL, 0, 0, NULL, 0, 0 }
+ };
+
+ PropertyMapEntry* pEntry = s_aDesriptorProperties;
+ while ( pEntry->mpName )
+ {
+ s_aProperties[ ::rtl::OUString::createFromAscii( pEntry->mpName ) ] = pEntry;
+ ++pEntry;
+ }
+ }
+
+ return s_aProperties;
+ }
+
+ //--------------------------------------------------------------------
+ PropertyMapEntry* ODADescriptorImpl::getPropertyMapEntry( const DescriptorValues::const_iterator& _rPos )
+ {
+ const MapString2PropertyEntry& rProperties = getPropertyMap();
+
+ sal_Int32 nNeededHandle = (sal_Int32)(_rPos->first);
+
+ for ( MapString2PropertyEntry::const_iterator loop = rProperties.begin();
+ loop != rProperties.end();
+ ++loop
+ )
+ {
+ if ( nNeededHandle == loop->second->mnHandle )
+ return loop->second;
+ }
+ throw RuntimeException();
+ }
+
+ //--------------------------------------------------------------------
+ PropertyValue ODADescriptorImpl::buildPropertyValue( const DescriptorValues::const_iterator& _rPos )
+ {
+ // the map entry
+ PropertyMapEntry* pProperty = getPropertyMapEntry( _rPos );
+
+ // build the property value
+ PropertyValue aReturn;
+ aReturn.Name = ::rtl::OUString( pProperty->mpName, pProperty->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ aReturn.Handle = pProperty->mnHandle;
+ aReturn.Value = _rPos->second;
+ aReturn.State = PropertyState_DIRECT_VALUE;
+
+ // outta here
+ return aReturn;
+ }
+
+ //--------------------------------------------------------------------
+ void ODADescriptorImpl::updateSequence()
+ {
+ if (!m_bSequenceOutOfDate)
+ return;
+
+ m_aAsSequence.realloc(m_aValues.size());
+ PropertyValue* pValue = m_aAsSequence.getArray();
+
+ // loop through all our values
+ for ( DescriptorValues::const_iterator aLoop = m_aValues.begin();
+ aLoop != m_aValues.end();
+ ++aLoop, ++pValue
+ )
+ {
+ *pValue = buildPropertyValue(aLoop);
+ }
+
+ // don't need to rebuild next time
+ m_bSequenceOutOfDate = sal_False;
+ }
+
+ //--------------------------------------------------------------------
+ void ODADescriptorImpl::updateSet()
+ {
+ if (!m_bSetOutOfDate)
+ return;
+
+ // will be the current values
+ Sequence< PropertyValue > aValuesToSet(m_aValues.size());
+ PropertyValue* pValuesToSet = aValuesToSet.getArray();
+
+ // build a new property set info
+ PropertySetInfo* pPropSetInfo = new PropertySetInfo;
+
+ // loop through all our values
+ for ( DescriptorValues::const_iterator aLoop = m_aValues.begin();
+ aLoop != m_aValues.end();
+ ++aLoop, ++pValuesToSet
+ )
+ {
+ PropertyMapEntry* pMapEntry = getPropertyMapEntry( aLoop );
+ pPropSetInfo->add( pMapEntry, 1 );
+
+ *pValuesToSet = buildPropertyValue(aLoop);
+ }
+
+ // create the generic set
+ m_xAsSet = GenericPropertySet_CreateInstance( pPropSetInfo );
+
+ // no we have the set, still need to set the current values
+ const PropertyValue* pSetValues = aValuesToSet.getConstArray();
+ const PropertyValue* pSetValuesEnd = pSetValues + aValuesToSet.getLength();
+ for (; pSetValues != pSetValuesEnd; ++pSetValues)
+ m_xAsSet->setPropertyValue(pSetValues->Name, pSetValues->Value);
+
+ // don't need to rebuild next time
+ m_bSetOutOfDate = sal_True;
+ }
+#endif
+
+ //====================================================================
+ //= ODataAccessDescriptor
+ //====================================================================
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::ODataAccessDescriptor()
+#ifndef SVX_LIGHT
+ :m_pImpl(new ODADescriptorImpl)
+#else
+ :m_pImpl(NULL)
+#endif
+ {
+ }
+
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::ODataAccessDescriptor( const ODataAccessDescriptor& _rSource )
+#ifndef SVX_LIGHT
+ :m_pImpl(new ODADescriptorImpl(*_rSource.m_pImpl))
+#else
+ :m_pImpl(NULL)
+#endif
+ {
+ }
+
+ //--------------------------------------------------------------------
+ const ODataAccessDescriptor& ODataAccessDescriptor::operator=(const ODataAccessDescriptor& _rSource)
+ {
+#ifndef SVX_LIGHT
+ delete m_pImpl;
+ m_pImpl = new ODADescriptorImpl(*_rSource.m_pImpl);
+#else
+ OSL_ENSURE(sal_False, "ODataAccessDescriptor::operator=: not available in the SVX_LIGHT version!");
+#endif
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::ODataAccessDescriptor( const Reference< XPropertySet >& _rValues )
+#ifndef SVX_LIGHT
+ :m_pImpl(new ODADescriptorImpl)
+#else
+ :m_pImpl(NULL)
+#endif
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->buildFrom(_rValues);
+#else
+ OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::ODataAccessDescriptor( const Any& _rValues )
+#ifndef SVX_LIGHT
+ :m_pImpl(new ODADescriptorImpl)
+#else
+ :m_pImpl(NULL)
+#endif
+ {
+#ifndef SVX_LIGHT
+ // check if we know the format in the Any
+ Sequence< PropertyValue > aValues;
+ Reference< XPropertySet > xValues;
+ if ( _rValues >>= aValues )
+ m_pImpl->buildFrom( aValues );
+ else if ( _rValues >>= xValues )
+ m_pImpl->buildFrom( xValues );
+#else
+ OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::ODataAccessDescriptor( const Sequence< PropertyValue >& _rValues )
+#ifndef SVX_LIGHT
+ :m_pImpl(new ODADescriptorImpl)
+#else
+ :m_pImpl(NULL)
+#endif
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->buildFrom(_rValues);
+#else
+ OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ ODataAccessDescriptor::~ODataAccessDescriptor()
+ {
+ delete m_pImpl;
+ }
+
+ //--------------------------------------------------------------------
+ void ODataAccessDescriptor::clear()
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->m_aValues.clear();
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ void ODataAccessDescriptor::erase(DataAccessDescriptorProperty _eWhich)
+ {
+#ifndef SVX_LIGHT
+ OSL_ENSURE(has(_eWhich), "ODataAccessDescriptor::erase: invalid call!");
+ if (has(_eWhich))
+ m_pImpl->m_aValues.erase(_eWhich);
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool ODataAccessDescriptor::has(DataAccessDescriptorProperty _eWhich) const
+ {
+#ifndef SVX_LIGHT
+ return m_pImpl->m_aValues.find(_eWhich) != m_pImpl->m_aValues.end();
+#else
+ return sal_False;
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ const Any& ODataAccessDescriptor::operator [] ( DataAccessDescriptorProperty _eWhich ) const
+ {
+#ifndef SVX_LIGHT
+ if (!has(_eWhich))
+ {
+ OSL_ENSURE(sal_False, "ODataAccessDescriptor::operator[]: invalid acessor!");
+ static const Any aDummy;
+ return aDummy;
+ }
+
+ return m_pImpl->m_aValues[_eWhich];
+#else
+ static const Any aDummy;
+ return aDummy;
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ Any& ODataAccessDescriptor::operator[] ( DataAccessDescriptorProperty _eWhich )
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->invalidateExternRepresentations();
+ return m_pImpl->m_aValues[_eWhich];
+#else
+ static const Any aDummy;
+ return aDummy;
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ void ODataAccessDescriptor::initializeFrom(const Reference< XPropertySet >& _rxValues, sal_Bool _bClear)
+ {
+#ifndef SVX_LIGHT
+ if (_bClear)
+ clear();
+ m_pImpl->buildFrom(_rxValues);
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ void ODataAccessDescriptor::initializeFrom(const Sequence< PropertyValue >& _rValues, sal_Bool _bClear)
+ {
+#ifndef SVX_LIGHT
+ if (_bClear)
+ clear();
+ m_pImpl->buildFrom(_rValues);
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< PropertyValue > ODataAccessDescriptor::createPropertyValueSequence()
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->updateSequence();
+ return m_pImpl->m_aAsSequence;
+#else
+ return Sequence< PropertyValue >();
+#endif
+ }
+ //--------------------------------------------------------------------
+ Sequence< Any > ODataAccessDescriptor::createAnySequence()
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->updateSequence();
+ Sequence< Any > aRet(m_pImpl->m_aAsSequence.getLength());
+ const PropertyValue* pBegin = m_pImpl->m_aAsSequence.getConstArray();
+ const PropertyValue* pEnd = pBegin + m_pImpl->m_aAsSequence.getLength();
+ for(sal_Int32 i=0;pBegin != pEnd;++pBegin,++i)
+ aRet[i] <<= *pBegin;
+ return aRet;
+#else
+ return Sequence< createAnySequence >();
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XPropertySet > ODataAccessDescriptor::createPropertySet()
+ {
+#ifndef SVX_LIGHT
+ m_pImpl->updateSet();
+ return m_pImpl->m_xAsSet;
+#else
+ return Reference< XPropertySet >();
+#endif
+ }
+ //--------------------------------------------------------------------
+ ::rtl::OUString ODataAccessDescriptor::getDataSource() const
+ {
+#ifndef SVX_LIGHT
+ ::rtl::OUString sDataSourceName;
+ if ( has(daDataSource) )
+ (*this)[daDataSource] >>= sDataSourceName;
+ else if ( has(daDatabaseLocation) )
+ (*this)[daDatabaseLocation] >>= sDataSourceName;
+ return sDataSourceName;
+#else
+ return ::rtl::OUString();
+#endif
+ }
+ //--------------------------------------------------------------------
+ void ODataAccessDescriptor::setDataSource(const ::rtl::OUString& _sDataSourceNameOrLocation)
+ {
+#ifndef SVX_LIGHT
+ if ( _sDataSourceNameOrLocation.getLength() )
+ {
+ INetURLObject aURL(_sDataSourceNameOrLocation);
+ (*this)[ (( aURL.GetProtocol() == INET_PROT_FILE ) ? daDatabaseLocation : daDataSource)] <<= _sDataSourceNameOrLocation;
+ }
+ else
+ (*this)[ daDataSource ] <<= ::rtl::OUString();
+#endif
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/databaselocationinput.cxx b/svx/source/form/databaselocationinput.cxx
new file mode 100644
index 000000000000..bd3d746f48b3
--- /dev/null
+++ b/svx/source/form/databaselocationinput.cxx
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "svx/databaselocationinput.hxx"
+#include "svx/dialmgr.hxx"
+
+#include "fmresids.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <svtools/urlcontrol.hxx>
+#include <svl/filenotation.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/confignode.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <vcl/button.hxx>
+#include <vcl/msgbox.hxx>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::Exception;
+ /** === end UNO using === **/
+ namespace TemplateDescription = ::com::sun::star::ui::dialogs::TemplateDescription;
+
+ //====================================================================
+ //= DatabaseLocationInputController_Impl
+ //====================================================================
+ class DatabaseLocationInputController_Impl
+ {
+ public:
+ DatabaseLocationInputController_Impl(
+ const ::comphelper::ComponentContext& _rContext,
+ ::svt::OFileURLControl& _rLocationInput,
+ PushButton& _rBrowseButton
+ );
+ ~DatabaseLocationInputController_Impl();
+
+ bool prepareCommit();
+ void setURL( const String& _rURL );
+ String getURL() const;
+
+ private:
+ void impl_initFilterProperties_nothrow();
+ void impl_onBrowseButtonClicked();
+ void impl_onLocationModified();
+ String impl_getCurrentURL() const;
+
+ DECL_LINK( OnControlAction, VclWindowEvent* );
+
+ private:
+ const ::comphelper::ComponentContext m_aContext;
+ ::svt::OFileURLControl& m_rLocationInput;
+ PushButton& m_rBrowseButton;
+ Sequence< ::rtl::OUString > m_aFilterExtensions;
+ ::rtl::OUString m_sFilterUIName;
+ bool m_bNeedExistenceCheck;
+ };
+
+ //--------------------------------------------------------------------
+ DatabaseLocationInputController_Impl::DatabaseLocationInputController_Impl( const ::comphelper::ComponentContext& _rContext,
+ ::svt::OFileURLControl& _rLocationInput, PushButton& _rBrowseButton )
+ :m_aContext( _rContext )
+ ,m_rLocationInput( _rLocationInput )
+ ,m_rBrowseButton( _rBrowseButton )
+ ,m_aFilterExtensions()
+ ,m_sFilterUIName()
+ ,m_bNeedExistenceCheck( true )
+ {
+ impl_initFilterProperties_nothrow();
+
+ // forward the allowed extensions to the input control
+ ::rtl::OUStringBuffer aExtensionList;
+ for ( const ::rtl::OUString* pExtension = m_aFilterExtensions.getConstArray();
+ pExtension != m_aFilterExtensions.getConstArray() + m_aFilterExtensions.getLength();
+ ++pExtension
+ )
+ {
+ aExtensionList.append( *pExtension );
+ aExtensionList.append( (sal_Unicode)';' );
+ }
+ m_rLocationInput.SetFilter( aExtensionList.makeStringAndClear() );
+
+ m_rBrowseButton.AddEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
+ m_rLocationInput.AddEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
+ }
+
+ //--------------------------------------------------------------------
+ DatabaseLocationInputController_Impl::~DatabaseLocationInputController_Impl()
+ {
+ m_rBrowseButton.RemoveEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
+ m_rLocationInput.RemoveEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
+ }
+
+ //--------------------------------------------------------------------
+ bool DatabaseLocationInputController_Impl::prepareCommit()
+ {
+ ::rtl::OUString sURL( impl_getCurrentURL() );
+ if ( !sURL.getLength() )
+ return false;
+
+ // check if the name exists
+ if ( m_bNeedExistenceCheck )
+ {
+ if ( ::utl::UCBContentHelper::Exists( sURL ) )
+ {
+ QueryBox aBox( m_rLocationInput.GetSystemWindow(), WB_YES_NO, SVX_RES( RID_STR_ALREADYEXISTOVERWRITE ) );
+ if ( aBox.Execute() != RET_YES )
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ void DatabaseLocationInputController_Impl::setURL( const String& _rURL )
+ {
+ ::svt::OFileNotation aTransformer( _rURL );
+ m_rLocationInput.SetText( aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
+ }
+
+ //--------------------------------------------------------------------
+ String DatabaseLocationInputController_Impl::getURL() const
+ {
+ return impl_getCurrentURL();
+ }
+
+ //--------------------------------------------------------------------
+ void DatabaseLocationInputController_Impl::impl_initFilterProperties_nothrow()
+ {
+ try
+ {
+ // get the name of the default filter for database documents
+ ::utl::OConfigurationTreeRoot aConfig(
+ ::utl::OConfigurationTreeRoot::createWithServiceFactory(
+ m_aContext.getLegacyServiceFactory(),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/com.sun.star.sdb.OfficeDatabaseDocument" ) )
+ ) );
+ ::rtl::OUString sDatabaseFilter;
+ OSL_VERIFY( aConfig.getNodeValue( "ooSetupFactoryActualFilter" ) >>= sDatabaseFilter );
+
+ // get the type this filter is responsible for
+ Reference< XNameAccess > xFilterFactory(
+ m_aContext.createComponent( "com.sun.star.document.FilterFactory" ),
+ UNO_QUERY_THROW );
+ ::comphelper::NamedValueCollection aFilterProperties( xFilterFactory->getByName( sDatabaseFilter ) );
+ ::rtl::OUString sDocumentType = aFilterProperties.getOrDefault( "Type", ::rtl::OUString() );
+
+ // get the extension(s) for this type
+ Reference< XNameAccess > xTypeDetection(
+ m_aContext.createComponent( "com.sun.star.document.TypeDetection" ),
+ UNO_QUERY_THROW );
+
+ ::comphelper::NamedValueCollection aTypeProperties( xTypeDetection->getByName( sDocumentType ) );
+ m_aFilterExtensions = aTypeProperties.getOrDefault( "Extensions", m_aFilterExtensions );
+ m_sFilterUIName = aTypeProperties.getOrDefault( "UIName", m_sFilterUIName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // ensure we have at least one extension
+ OSL_ENSURE( m_aFilterExtensions.getLength(),
+ "DatabaseLocationInputController_Impl::impl_initFilterProperties_nothrow: unable to determine the file extension(s)!" );
+ if ( m_aFilterExtensions.getLength() == 0 )
+ {
+ m_aFilterExtensions.realloc(1);
+ m_aFilterExtensions[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.odb" ) );
+ }
+ }
+
+ // -----------------------------------------------------------------------------
+ IMPL_LINK( DatabaseLocationInputController_Impl, OnControlAction, VclWindowEvent*, _pEvent )
+ {
+ if ( ( _pEvent->GetWindow() == &m_rBrowseButton )
+ && ( _pEvent->GetId() == VCLEVENT_BUTTON_CLICK )
+ )
+ {
+ impl_onBrowseButtonClicked();
+ }
+
+ if ( ( _pEvent->GetWindow() == &m_rLocationInput )
+ && ( _pEvent->GetId() == VCLEVENT_EDIT_MODIFY )
+ )
+ {
+ impl_onLocationModified();
+ }
+
+ return 0L;
+ }
+
+ // -----------------------------------------------------------------------------
+ String DatabaseLocationInputController_Impl::impl_getCurrentURL() const
+ {
+ String sCurrentFile( m_rLocationInput.GetText() );
+ if ( sCurrentFile.Len() )
+ {
+ ::svt::OFileNotation aCurrentFile( sCurrentFile );
+ sCurrentFile = aCurrentFile.get( ::svt::OFileNotation::N_URL );
+ }
+ return sCurrentFile;
+ }
+
+ // -----------------------------------------------------------------------------
+ void DatabaseLocationInputController_Impl::impl_onBrowseButtonClicked()
+ {
+ ::sfx2::FileDialogHelper aFileDlg(
+ TemplateDescription::FILESAVE_AUTOEXTENSION,
+ WB_STDMODAL | WB_SAVEAS,
+ m_rLocationInput.GetSystemWindow()
+ );
+ aFileDlg.SetDisplayDirectory( impl_getCurrentURL() );
+
+ aFileDlg.AddFilter( m_sFilterUIName, ::rtl::OUStringBuffer().appendAscii( "*." ).append( m_aFilterExtensions[0] ).makeStringAndClear() );
+ aFileDlg.SetCurrentFilter( m_sFilterUIName );
+
+ if ( aFileDlg.Execute() == ERRCODE_NONE )
+ {
+ INetURLObject aURL( aFileDlg.GetPath() );
+ if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
+ {
+ ::svt::OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
+ m_rLocationInput.SetText( aFileNotation.get( ::svt::OFileNotation::N_SYSTEM ) );
+ m_rLocationInput.GetModifyHdl().Call( &m_rLocationInput );
+ // the dialog already checked for the file's existence, so we don't need to, again
+ m_bNeedExistenceCheck = false;
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------
+ void DatabaseLocationInputController_Impl::impl_onLocationModified()
+ {
+ m_bNeedExistenceCheck = true;
+ }
+
+ //====================================================================
+ //= DatabaseLocationInputController
+ //====================================================================
+ //--------------------------------------------------------------------
+ DatabaseLocationInputController::DatabaseLocationInputController( const ::comphelper::ComponentContext& _rContext,
+ ::svt::OFileURLControl& _rLocationInput, PushButton& _rBrowseButton )
+ :m_pImpl( new DatabaseLocationInputController_Impl( _rContext, _rLocationInput, _rBrowseButton ) )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ DatabaseLocationInputController::~DatabaseLocationInputController()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool DatabaseLocationInputController::prepareCommit()
+ {
+ return m_pImpl->prepareCommit();
+ }
+
+ //--------------------------------------------------------------------
+ void DatabaseLocationInputController::setURL( const String& _rURL )
+ {
+ m_pImpl->setURL( _rURL );
+ }
+
+ //--------------------------------------------------------------------
+ String DatabaseLocationInputController::getURL() const
+ {
+ return m_pImpl->getURL();
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/datalistener.cxx b/svx/source/form/datalistener.cxx
new file mode 100644
index 000000000000..35f6b32cc1a7
--- /dev/null
+++ b/svx/source/form/datalistener.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "datalistener.hxx"
+#include "datanavi.hxx"
+
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::dom::events;
+
+//............................................................................
+namespace svxform
+{
+//............................................................................
+
+ DataListener::DataListener( DataNavigatorWindow* pNaviWin ) :
+
+ m_pNaviWin( pNaviWin )
+
+ {
+ DBG_ASSERT( m_pNaviWin, "DataListener::Ctor(): no navigator win" );
+ }
+
+ DataListener::~DataListener()
+ {
+ }
+
+ // XContainerListener
+ void SAL_CALL DataListener::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
+ {
+ m_pNaviWin->NotifyChanges();
+ }
+
+ void SAL_CALL DataListener::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
+ {
+ m_pNaviWin->NotifyChanges();
+ }
+
+ void SAL_CALL DataListener::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
+ {
+ m_pNaviWin->NotifyChanges();
+ }
+
+ // XFrameActionListener
+ void SAL_CALL DataListener::frameAction( const FrameActionEvent& rActionEvt ) throw (RuntimeException)
+ {
+ if ( FrameAction_COMPONENT_ATTACHED == rActionEvt.Action ||
+ FrameAction_COMPONENT_REATTACHED == rActionEvt.Action )
+ {
+ m_pNaviWin->NotifyChanges( FrameAction_COMPONENT_REATTACHED == rActionEvt.Action );
+ }
+ }
+
+ // xml::dom::events::XEventListener
+ void SAL_CALL DataListener::handleEvent( const Reference< XEvent >& /*evt*/ ) throw (RuntimeException)
+ {
+ m_pNaviWin->NotifyChanges();
+ }
+
+ // lang::XEventListener
+ void SAL_CALL DataListener::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
+ {
+ DBG_ERRORFILE( "disposing" );
+ }
+
+//............................................................................
+} // namespace svxform
+//............................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/datanavi.cxx b/svx/source/form/datanavi.cxx
new file mode 100644
index 000000000000..25c05260338c
--- /dev/null
+++ b/svx/source/form/datanavi.cxx
@@ -0,0 +1,3727 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+#include "datanavi.hxx"
+#include "fmservs.hxx"
+
+#include "datanavi.hrc"
+#include "fmresids.hrc"
+#include "fmhelp.hrc"
+#include <svx/svxids.hrc>
+#include <tools/rcid.h>
+#include <tools/diagnose_ex.h>
+#include "xmlexchg.hxx"
+#include <svx/dialmgr.hxx>
+#include <svx/fmshell.hxx>
+#include <svtools/miscopt.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/viewoptions.hxx>
+#include <svtools/svtools.hrc>
+#include <sfx2/app.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include "com/sun/star/ui/dialogs/TemplateDescription.hpp"
+#include <com/sun/star/xforms/XFormsSupplier.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/DOMException.hpp>
+#include <com/sun/star/form/binding/XValueBinding.hpp>
+#include <comphelper/processfactory.hxx>
+#include <rtl/logfile.hxx>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::dom::events;
+using namespace ::svx;
+
+namespace css = ::com::sun::star;
+
+#define CFGNAME_DATANAVIGATOR DEFINE_CONST_UNICODE("DataNavigator")
+#define CFGNAME_SHOWDETAILS DEFINE_CONST_UNICODE("ShowDetails")
+#define MSG_VARIABLE DEFINE_CONST_UNICODE("%1")
+#define MODELNAME DEFINE_CONST_UNICODE("$MODELNAME")
+#define INSTANCENAME DEFINE_CONST_UNICODE("$INSTANCENAME")
+#define ELEMENTNAME DEFINE_CONST_UNICODE("$ELEMENTNAME")
+#define ATTRIBUTENAME DEFINE_CONST_UNICODE("$ATTRIBUTENAME")
+#define SUBMISSIONNAME DEFINE_CONST_UNICODE("$SUBMISSIONNAME")
+#define BINDINGNAME DEFINE_CONST_UNICODE("$BINDINGNAME")
+
+//............................................................................
+namespace svxform
+{
+//............................................................................
+
+ // properties of instance
+ #define PN_INSTANCE_MODEL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Instance" ) )
+ #define PN_INSTANCE_ID ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ID" ) )
+ #define PN_INSTANCE_URL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) )
+ #define PN_INSTANCE_URLONCE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URLOnce" ) )
+
+ // properties of binding
+ #define PN_BINDING_ID ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BindingID" ) )
+ #define PN_BINDING_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BindingExpression" ) )
+ #define PN_BINDING_MODEL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) )
+ #define PN_BINDING_NAMESPACES ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModelNamespaces" ) )
+ #define PN_BINDING_MODELID ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModelID" ) )
+ #define PN_READONLY_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ReadonlyExpression" ) )
+ #define PN_RELEVANT_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RelevantExpression" ) )
+ #define PN_REQUIRED_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RequiredExpression" ) )
+ #define PN_CONSTRAINT_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ConstraintExpression" ) )
+ #define PN_CALCULATE_EXPR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CalculateExpression" ) )
+ #define PN_BINDING_TYPE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) )
+ #define PN_BINDING_READONLY ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ReadOnly" ) )
+ #define PN_BINDING_ENABLED ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enabled" ) )
+
+ // properties of submission
+ #define PN_SUBMISSION_ID ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ID" ) )
+ #define PN_SUBMISSION_BIND ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Bind" ) )
+ #define PN_SUBMISSION_REF ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Ref" ) )
+ #define PN_SUBMISSION_ACTION ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Action" ) )
+ #define PN_SUBMISSION_METHOD ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Method" ) )
+ #define PN_SUBMISSION_MODEL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) )
+ #define PN_SUBMISSION_REPLACE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Replace" ) )
+
+ // submission methods
+ #define SUBMITMETHOD_POST ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) )
+ #define SUBMITMETHOD_GET ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "get" ) )
+ #define SUBMITMETHOD_PUT ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "put" ) )
+
+ // other const strings
+ #define TRUE_VALUE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true()" ) )
+ #define FALSE_VALUE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false()" ) )
+ #define NEW_ELEMENT ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "newElement" ) )
+ #define NEW_ATTRIBUTE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "newAttribute" ) )
+ #define EVENTTYPE_SUBTREE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DOMSubtreeModified" ) )
+ #define EVENTTYPE_CHARDATA ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DOMCharacterDataModified" ) )
+ #define EVENTTYPE_ATTR ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DOMAttrModified" ) )
+
+ #define MIN_PAGE_COUNT 3 // at least one instance, one submission and one binding page
+
+ struct ItemNode
+ {
+ Reference< css::xml::dom::XNode > m_xNode;
+ Reference< XPropertySet > m_xPropSet;
+
+ ItemNode( const Reference< css::xml::dom::XNode >& _rxNode ) :
+ m_xNode( _rxNode ) {}
+ ItemNode( const Reference< XPropertySet >& _rxSet ) :
+ m_xPropSet( _rxSet ) {}
+
+ DataGroupType GetDataGroupType() const;
+ };
+
+ //========================================================================
+ // class DataTreeListBox
+ //========================================================================
+ DataTreeListBox::DataTreeListBox( XFormsPage* pPage, DataGroupType _eGroup, const ResId& rResId ) :
+
+ SvTreeListBox( pPage, rResId ),
+
+ m_pXFormsPage ( pPage ),
+ m_eGroup ( _eGroup )
+
+ {
+ EnableContextMenuHandling();
+
+ if ( DGTInstance == m_eGroup )
+ SetDragDropMode( SV_DRAGDROP_CTRL_MOVE |SV_DRAGDROP_CTRL_COPY | SV_DRAGDROP_APP_COPY );
+ }
+
+ DataTreeListBox::~DataTreeListBox()
+ {
+ DeleteAndClear();
+ }
+
+ sal_Int8 DataTreeListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
+ {
+ return DND_ACTION_NONE;
+ }
+ sal_Int8 DataTreeListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
+ {
+ return DND_ACTION_NONE;
+ }
+ void DataTreeListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
+ {
+ SvLBoxEntry* pSelected = FirstSelected();
+ if ( !pSelected )
+ // no drag without an entry
+ return;
+
+ if ( m_eGroup == DGTBinding )
+ // for the moment, bindings cannot be dragged.
+ // #i59395# / 2005-12-15 / frank.schoenheit@sun.com
+ return;
+
+ // GetServiceNameForNode() requires a datatype repository which
+ // will be automatically build if requested???
+ Reference< css::xforms::XModel > xModel( m_pXFormsPage->GetXFormsHelper(), UNO_QUERY );
+ Reference< css::xforms::XDataTypeRepository > xDataTypes =
+ xModel->getDataTypeRepository();
+ if(!xDataTypes.is())
+ return;
+
+ using namespace ::com::sun::star::uno;
+ typedef com::sun::star::form::binding::XValueBinding XValueBinding_t;
+
+ ItemNode *pItemNode = static_cast<ItemNode*>(pSelected->GetUserData());
+
+ if ( !pItemNode )
+ {
+ // the only known (and allowed?) case where this happens are sub-entries of a submission
+ // entry
+ DBG_ASSERT( DGTSubmission == m_eGroup, "DataTreeListBox::StartDrag: how this?" );
+ pSelected = GetParent( pSelected );
+ DBG_ASSERT( pSelected && !GetParent( pSelected ), "DataTreeListBox::StartDrag: what kind of entry *is* this?" );
+ // on the submission page, we have only top-level entries (the submission themself)
+ // plus direct children of those (facets of a submission)
+ pItemNode = pSelected ? static_cast< ItemNode* >( pSelected->GetUserData() ) : NULL;
+ if ( !pItemNode )
+ return;
+ }
+
+ OXFormsDescriptor desc;
+ desc.szName = GetEntryText(pSelected);
+ if(pItemNode->m_xNode.is()) {
+ // a valid node interface tells us that we need to create a control from a binding
+ desc.szServiceName = m_pXFormsPage->GetServiceNameForNode(pItemNode->m_xNode);
+ desc.xPropSet = m_pXFormsPage->GetBindingForNode(pItemNode->m_xNode);
+ DBG_ASSERT( desc.xPropSet.is(), "DataTreeListBox::StartDrag(): invalid node binding" );
+ }
+ else {
+ desc.szServiceName = FM_COMPONENT_COMMANDBUTTON;
+ desc.xPropSet = pItemNode->m_xPropSet;
+ }
+ OXFormsTransferable *pTransferable = new OXFormsTransferable(desc);
+ Reference< XTransferable > xEnsureDelete = pTransferable;
+ if(pTransferable) {
+ EndSelection();
+ pTransferable->StartDrag( this, DND_ACTION_COPY );
+ }
+ }
+
+ PopupMenu* DataTreeListBox::CreateContextMenu()
+ {
+ PopupMenu* pMenu = new PopupMenu( SVX_RES( RID_MENU_DATANAVIGATOR ) );
+ if ( DGTInstance == m_eGroup )
+ pMenu->RemoveItem( pMenu->GetItemPos( TBI_ITEM_ADD ) );
+ else
+ {
+ pMenu->RemoveItem( pMenu->GetItemPos( TBI_ITEM_ADD_ELEMENT ) );
+ pMenu->RemoveItem( pMenu->GetItemPos( TBI_ITEM_ADD_ATTRIBUTE ) );
+
+ if ( DGTSubmission == m_eGroup )
+ {
+ pMenu->SetItemText( TBI_ITEM_ADD, SVX_RESSTR( RID_STR_DATANAV_ADD_SUBMISSION ) );
+ pMenu->SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( RID_STR_DATANAV_EDIT_SUBMISSION ) );
+ pMenu->SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( RID_STR_DATANAV_REMOVE_SUBMISSION ) );
+ }
+ else
+ {
+ pMenu->SetItemText( TBI_ITEM_ADD, SVX_RESSTR( RID_STR_DATANAV_ADD_BINDING ) );
+ pMenu->SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( RID_STR_DATANAV_EDIT_BINDING ) );
+ pMenu->SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( RID_STR_DATANAV_REMOVE_BINDING ) );
+ }
+ }
+ m_pXFormsPage->EnableMenuItems( pMenu );
+ return pMenu;
+ }
+
+ void DataTreeListBox::ExcecuteContextMenuAction( USHORT _nSelectedPopupEntry )
+ {
+ m_pXFormsPage->DoMenuAction( _nSelectedPopupEntry );
+ }
+
+ void DataTreeListBox::RemoveEntry( SvLBoxEntry* _pEntry )
+ {
+ if ( _pEntry )
+ {
+ delete static_cast< ItemNode* >( _pEntry->GetUserData() );
+ SvTreeListBox::GetModel()->Remove( _pEntry );
+ }
+ }
+
+ void DataTreeListBox::DeleteAndClear()
+ {
+ ULONG i, nCount = GetEntryCount();
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvLBoxEntry* pEntry = GetEntry(i);
+ if ( pEntry )
+ delete static_cast< ItemNode* >( pEntry->GetUserData() );
+ }
+
+ Clear();
+ }
+
+ //========================================================================
+ // class XFormsPage
+ //========================================================================
+ XFormsPage::XFormsPage( Window* pParent, DataNavigatorWindow* _pNaviWin, DataGroupType _eGroup ) :
+
+ TabPage( pParent, SVX_RES( RID_SVX_XFORMS_TABPAGES ) ),
+
+ m_aToolBox ( this, SVX_RES( TB_ITEMS ) ),
+ m_aItemList ( this, _eGroup, SVX_RES( LB_ITEMS ) ),
+ m_pNaviWin ( _pNaviWin ),
+ m_bHasModel ( false ),
+ m_eGroup ( _eGroup ),
+ m_TbxImageList ( SVX_RES( IL_TBX_BMPS ) )
+
+ {
+ FreeResource();
+
+ const ImageList& rImageList = m_TbxImageList;
+ m_aToolBox.SetItemImage( TBI_ITEM_ADD, rImageList.GetImage( IID_ITEM_ADD ) );
+ m_aToolBox.SetItemImage( TBI_ITEM_ADD_ELEMENT, rImageList.GetImage( IID_ITEM_ADD_ELEMENT ) );
+ m_aToolBox.SetItemImage( TBI_ITEM_ADD_ATTRIBUTE, rImageList.GetImage( IID_ITEM_ADD_ATTRIBUTE ) );
+ m_aToolBox.SetItemImage( TBI_ITEM_EDIT, rImageList.GetImage( IID_ITEM_EDIT ) );
+ m_aToolBox.SetItemImage( TBI_ITEM_REMOVE, rImageList.GetImage( IID_ITEM_REMOVE ) );
+
+ if ( DGTInstance == m_eGroup )
+ m_aToolBox.RemoveItem( m_aToolBox.GetItemPos( TBI_ITEM_ADD ) );
+ else
+ {
+ m_aToolBox.RemoveItem( m_aToolBox.GetItemPos( TBI_ITEM_ADD_ELEMENT ) );
+ m_aToolBox.RemoveItem( m_aToolBox.GetItemPos( TBI_ITEM_ADD_ATTRIBUTE ) );
+
+ if ( DGTSubmission == m_eGroup )
+ {
+ m_aToolBox.SetItemText( TBI_ITEM_ADD, SVX_RESSTR( RID_STR_DATANAV_ADD_SUBMISSION ) );
+ m_aToolBox.SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( RID_STR_DATANAV_EDIT_SUBMISSION ) );
+ m_aToolBox.SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( RID_STR_DATANAV_REMOVE_SUBMISSION ) );
+ }
+ else
+ {
+ m_aToolBox.SetItemText( TBI_ITEM_ADD, SVX_RESSTR( RID_STR_DATANAV_ADD_BINDING ) );
+ m_aToolBox.SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( RID_STR_DATANAV_EDIT_BINDING ) );
+ m_aToolBox.SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( RID_STR_DATANAV_REMOVE_BINDING ) );
+ }
+ }
+
+ const Size aTbxSz( m_aToolBox.CalcWindowSizePixel() );
+ m_aToolBox.SetSizePixel( aTbxSz );
+ m_aToolBox.SetOutStyle( SvtMiscOptions().GetToolboxStyle() );
+ m_aToolBox.SetSelectHdl( LINK( this, XFormsPage, TbxSelectHdl ) );
+ Point aPos = m_aItemList.GetPosPixel();
+ aPos.Y() = aTbxSz.Height();
+ m_aItemList.SetPosPixel( aPos );
+
+ m_aItemList.SetSelectHdl( LINK( this, XFormsPage, ItemSelectHdl ) );
+ m_aItemList.SetNodeDefaultImages();
+ WinBits nBits = WB_BORDER | WB_TABSTOP | WB_HIDESELECTION | WB_NOINITIALSELECTION;
+ if ( DGTInstance == m_eGroup || DGTSubmission == m_eGroup )
+ nBits |= WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT;
+ m_aItemList.SetWindowBits( m_aItemList.GetStyle() | nBits );
+ m_aItemList.Show();
+ ItemSelectHdl( &m_aItemList );
+ }
+ //------------------------------------------------------------------------
+ XFormsPage::~XFormsPage()
+ {
+ }
+ //------------------------------------------------------------------------
+ IMPL_LINK( XFormsPage, TbxSelectHdl, ToolBox *, EMPTYARG )
+ {
+ DoToolBoxAction( m_aToolBox.GetCurItemId() );
+ return 0;
+ }
+ //------------------------------------------------------------------------
+ IMPL_LINK( XFormsPage, ItemSelectHdl, DataTreeListBox *, EMPTYARG )
+ {
+ EnableMenuItems( NULL );
+ return 0;
+ }
+ //------------------------------------------------------------------------
+ void XFormsPage::AddChildren(
+ SvLBoxEntry* _pParent, const ImageList& _rImgLst,
+ const Reference< css::xml::dom::XNode >& _xNode )
+ {
+ DBG_ASSERT( m_xUIHelper.is(), "XFormsPage::AddChildren(): invalid UIHelper" );
+
+ try
+ {
+ Reference< css::xml::dom::XNodeList > xNodeList = _xNode->getChildNodes();
+ if ( xNodeList.is() )
+ {
+ bool bShowDetails = m_pNaviWin->IsShowDetails();
+ sal_Int32 i, nNodeCount = xNodeList->getLength();
+ for ( i = 0; i < nNodeCount; ++i )
+ {
+ Reference< css::xml::dom::XNode > xChild = xNodeList->item(i);
+ css::xml::dom::NodeType eChildType = xChild->getNodeType();
+ Image aExpImg, aCollImg;
+ switch ( eChildType )
+ {
+ case css::xml::dom::NodeType_ATTRIBUTE_NODE:
+ aExpImg = aCollImg = _rImgLst.GetImage( IID_ATTRIBUTE );
+ break;
+ case css::xml::dom::NodeType_ELEMENT_NODE:
+ aExpImg = aCollImg = _rImgLst.GetImage( IID_ELEMENT );
+ break;
+ case css::xml::dom::NodeType_TEXT_NODE:
+ aExpImg = aCollImg = _rImgLst.GetImage( IID_TEXT );
+ break;
+ default:
+ aExpImg = aCollImg = _rImgLst.GetImage( IID_OTHER );
+ }
+
+ ::rtl::OUString sName = m_xUIHelper->getNodeDisplayName( xChild, bShowDetails );
+ if ( sName.getLength() > 0 )
+ {
+ ItemNode* pNode = new ItemNode( xChild );
+ SvLBoxEntry* pEntry = m_aItemList.InsertEntry(
+ sName, aExpImg, aCollImg, _pParent, FALSE, LIST_APPEND, pNode );
+ if ( xChild->hasAttributes() )
+ {
+ Reference< css::xml::dom::XNamedNodeMap > xMap = xChild->getAttributes();
+ if ( xMap.is() )
+ {
+ aExpImg = aCollImg = _rImgLst.GetImage( IID_ATTRIBUTE );
+ sal_Int32 j, nMapLen = xMap->getLength();
+ for ( j = 0; j < nMapLen; ++j )
+ {
+ Reference< css::xml::dom::XNode > xAttr = xMap->item(j);
+ pNode = new ItemNode( xAttr );
+ ::rtl::OUString sAttrName =
+ m_xUIHelper->getNodeDisplayName( xAttr, bShowDetails );
+ m_aItemList.InsertEntry(
+ sAttrName, aExpImg, aCollImg,
+ pEntry, FALSE, LIST_APPEND, pNode );
+ }
+ }
+ }
+ if ( xChild->hasChildNodes() )
+ AddChildren( pEntry, _rImgLst, xChild );
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ //------------------------------------------------------------------------
+ bool XFormsPage::DoToolBoxAction( USHORT _nToolBoxID ) {
+
+ bool bHandled = false;
+ bool bIsDocModified = false;
+ m_pNaviWin->DisableNotify( true );
+
+ switch ( _nToolBoxID )
+ {
+ case TBI_ITEM_ADD:
+ case TBI_ITEM_ADD_ELEMENT:
+ case TBI_ITEM_ADD_ATTRIBUTE:
+ {
+ bHandled = true;
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ DBG_ASSERT( xModel.is(), "XFormsPage::DoToolBoxAction(): Action without model" );
+ if ( DGTSubmission == m_eGroup )
+ {
+ AddSubmissionDialog aDlg( this, NULL, m_xUIHelper );
+ if ( aDlg.Execute() == RET_OK && aDlg.GetNewSubmission().is() )
+ {
+ try
+ {
+ Reference< css::xforms::XSubmission > xNewSubmission = aDlg.GetNewSubmission();
+ Reference< XSet > xSubmissions( xModel->getSubmissions(), UNO_QUERY );
+ xSubmissions->insert( makeAny( xNewSubmission ) );
+ Reference< XPropertySet > xNewPropSet( xNewSubmission, UNO_QUERY );
+ SvLBoxEntry* pEntry = AddEntry( xNewPropSet );
+ m_aItemList.Select( pEntry, TRUE );
+ bIsDocModified = true;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while adding submission" );
+ }
+ }
+ }
+ else
+ {
+ DataItemType eType = DITElement;
+ SvLBoxEntry* pEntry = m_aItemList.FirstSelected();
+ ItemNode* pNode = NULL;
+ Reference< css::xml::dom::XNode > xParentNode;
+ Reference< XPropertySet > xNewBinding;
+ USHORT nResId = 0;
+ bool bIsElement = true;
+ if ( DGTInstance == m_eGroup )
+ {
+ if ( m_sInstanceURL.Len() > 0 )
+ {
+ LinkedInstanceWarningBox aMsgBox( this );
+ if ( aMsgBox.Execute() != RET_OK )
+ return bHandled;
+ }
+
+ DBG_ASSERT( pEntry, "XFormsPage::DoToolBoxAction(): no entry" );
+ ItemNode* pParentNode = static_cast< ItemNode* >( pEntry->GetUserData() );
+ DBG_ASSERT( pParentNode, "XFormsPage::DoToolBoxAction(): no parent node" );
+ xParentNode = pParentNode->m_xNode;
+ Reference< css::xml::dom::XNode > xNewNode;
+ if ( TBI_ITEM_ADD_ELEMENT == _nToolBoxID )
+ {
+ try
+ {
+ nResId = RID_STR_DATANAV_ADD_ELEMENT;
+ xNewNode = m_xUIHelper->createElement( xParentNode, NEW_ELEMENT );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while create element" );
+ }
+ }
+ else
+ {
+ nResId = RID_STR_DATANAV_ADD_ATTRIBUTE;
+ bIsElement = false;
+ eType = DITAttribute;
+ try
+ {
+ xNewNode = m_xUIHelper->createAttribute( xParentNode, NEW_ATTRIBUTE );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while create attribute" );
+ }
+ }
+
+ try
+ {
+ xNewNode = xParentNode->appendChild( xNewNode );
+ }
+ catch ( css::xml::dom::DOMException& e )
+ {
+ if ( e.Code == css::xml::dom::DOMExceptionType_DOMSTRING_SIZE_ERR )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): domexception: size error" );
+ }
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): domexception while append child" );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while append child" );
+ }
+
+ try
+ {
+ Reference< css::xml::dom::XNode > xPNode;
+ if ( xNewNode.is() )
+ xPNode = xNewNode->getParentNode();
+ // attributes don't have parents in the DOM model
+ DBG_ASSERT( TBI_ITEM_ADD_ATTRIBUTE == _nToolBoxID
+ || xPNode.is(), "XFormsPage::DoToolboxAction(): node not added" );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+
+ try
+ {
+ m_xUIHelper->getBindingForNode( xNewNode, sal_True );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while get binding for node" );
+ }
+ pNode = new ItemNode( xNewNode );
+ }
+ else
+ {
+ try
+ {
+ nResId = RID_STR_DATANAV_ADD_BINDING;
+ xNewBinding = xModel->createBinding();
+ Reference< XSet > xBindings( xModel->getBindings(), UNO_QUERY );
+ xBindings->insert( makeAny( xNewBinding ) );
+ pNode = new ItemNode( xNewBinding );
+ eType = DITBinding;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolBoxAction(): exception while adding binding" );
+ }
+ }
+
+ AddDataItemDialog aDlg( this, pNode, m_xUIHelper );
+ aDlg.SetText( SVX_RESSTR( nResId ) );
+ aDlg.InitText( eType );
+ short nReturn = aDlg.Execute();
+ if ( DGTInstance == m_eGroup )
+ {
+ if ( RET_OK == nReturn )
+ {
+ SvLBoxEntry* pNewEntry = AddEntry( pNode, bIsElement );
+ m_aItemList.MakeVisible( pNewEntry );
+ m_aItemList.Select( pNewEntry, TRUE );
+ bIsDocModified = true;
+ }
+ else
+ {
+ try
+ {
+ Reference< css::xml::dom::XNode > xPNode;
+ Reference< css::xml::dom::XNode > xNode =
+ xParentNode->removeChild( pNode->m_xNode );
+ if ( xNode.is() )
+ xPNode = xNode->getParentNode();
+ DBG_ASSERT( !xPNode.is(), "XFormsPage::RemoveEntry(): node not removed" );
+ delete pNode;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+ }
+ }
+ else
+ {
+ if ( RET_OK == nReturn )
+ {
+ SvLBoxEntry* pNewEntry = AddEntry( xNewBinding );
+ m_aItemList.Select( pNewEntry, TRUE );
+ bIsDocModified = true;
+ }
+ else
+ {
+ try
+ {
+ Reference< XSet > xBindings( xModel->getBindings(), UNO_QUERY );
+ xBindings->remove( makeAny( xNewBinding ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+ }
+ delete pNode;
+ }
+ }
+ }
+ break;
+
+ case TBI_ITEM_EDIT:
+ {
+ bHandled = true;
+ SvLBoxEntry* pEntry = m_aItemList.FirstSelected();
+ if ( pEntry )
+ {
+ if ( DGTSubmission == m_eGroup && m_aItemList.GetParent( pEntry ) )
+ pEntry = m_aItemList.GetParent( pEntry );
+ ItemNode* pNode = static_cast< ItemNode* >( pEntry->GetUserData() );
+ if ( DGTInstance == m_eGroup || DGTBinding == m_eGroup )
+ {
+ if ( DGTInstance == m_eGroup && m_sInstanceURL.Len() > 0 )
+ {
+ LinkedInstanceWarningBox aMsgBox( this );
+ if ( aMsgBox.Execute() != RET_OK )
+ return bHandled;
+ }
+
+ AddDataItemDialog aDlg( this, pNode, m_xUIHelper );
+ DataItemType eType = DITElement;
+ USHORT nResId = RID_STR_DATANAV_EDIT_ELEMENT;
+ if ( pNode && pNode->m_xNode.is() )
+ {
+ try
+ {
+ css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
+ if ( eChildType == css::xml::dom::NodeType_ATTRIBUTE_NODE )
+ {
+ nResId = RID_STR_DATANAV_EDIT_ATTRIBUTE;
+ eType = DITAttribute;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+ }
+ else if ( DGTBinding == m_eGroup )
+ {
+ nResId = RID_STR_DATANAV_EDIT_BINDING;
+ eType = DITBinding;
+ }
+ aDlg.SetText( SVX_RESSTR( nResId ) );
+ aDlg.InitText( eType );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ // Set the new name
+ String sNewName;
+ if ( DGTInstance == m_eGroup )
+ {
+ try
+ {
+ sNewName = m_xUIHelper->getNodeDisplayName(
+ pNode->m_xNode, m_pNaviWin->IsShowDetails() );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+ }
+ else
+ {
+ try
+ {
+ String sDelim( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
+ ::rtl::OUString sTemp;
+ pNode->m_xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
+ sNewName += String( sTemp );
+ sNewName += sDelim;
+ pNode->m_xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
+ sNewName += String( sTemp );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::DoToolboxAction(): exception caught" );
+ }
+ }
+
+ m_aItemList.SetEntryText( pEntry, sNewName );
+ bIsDocModified = true;
+ }
+ }
+ else
+ {
+ AddSubmissionDialog aDlg( this, pNode, m_xUIHelper );
+ aDlg.SetText( SVX_RESSTR( RID_STR_DATANAV_EDIT_SUBMISSION ) );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ EditEntry( pNode->m_xPropSet );
+ bIsDocModified = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case TBI_ITEM_REMOVE:
+ {
+ bHandled = true;
+ if ( DGTInstance == m_eGroup && m_sInstanceURL.Len() > 0 )
+ {
+ LinkedInstanceWarningBox aMsgBox( this );
+ if ( aMsgBox.Execute() != RET_OK )
+ return bHandled;
+ }
+ bIsDocModified = RemoveEntry();
+ }
+ break;
+
+ case MID_INSERT_CONTROL:
+ {
+ OSL_ENSURE( false, "XFormsPage::DoToolboxAction: MID_INSERT_CONTROL not implemented, yet!" );
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false, "XFormsPage::DoToolboxAction: unknown ID!" );
+ break;
+ }
+
+ m_pNaviWin->DisableNotify( false );
+ EnableMenuItems( NULL );
+ if ( bIsDocModified )
+ m_pNaviWin->SetDocModified();
+ return bHandled;
+ }
+
+ //------------------------------------------------------------------------
+ SvLBoxEntry* XFormsPage::AddEntry( ItemNode* _pNewNode, bool _bIsElement )
+ {
+ SvLBoxEntry* pParent = m_aItemList.FirstSelected();
+ const ImageList& rImageList = m_pNaviWin->GetItemImageList();
+ USHORT nImageID = ( _bIsElement ) ? IID_ELEMENT : IID_ATTRIBUTE;
+ Image aImage = rImageList.GetImage( nImageID );
+ ::rtl::OUString sName;
+ try
+ {
+ sName = m_xUIHelper->getNodeDisplayName(
+ _pNewNode->m_xNode, m_pNaviWin->IsShowDetails() );
+ }
+ catch ( Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return m_aItemList.InsertEntry(
+ sName, aImage, aImage, pParent, FALSE, LIST_APPEND, _pNewNode );
+ }
+ //------------------------------------------------------------------------
+ class lcl_ResourceString
+ {
+ protected:
+ lcl_ResourceString()
+ {
+ }
+
+ lcl_ResourceString( const lcl_ResourceString& );
+
+ virtual ~lcl_ResourceString()
+ {
+ }
+
+ // load UI resources from resource file
+ void init()
+ {
+ // create a resource manager, for the svx resource file
+ // and the UI locale
+ ByteString aResourceFile( "svx" );
+ ResMgr* pResMgr = ResMgr::CreateResMgr(
+ aResourceFile.GetBuffer(),
+ Application::GetSettings().GetUILocale() );
+
+ // load the resources for the AddSubmission modal dialog.
+ // This will create our own resource context.
+ ResId aRes( RID_SVXDLG_ADD_SUBMISSION, *pResMgr );
+ aRes.SetRT( RSC_MODALDIALOG );
+ pResMgr->GetResource( aRes );
+
+ // now, we can access the local resources from the dialog's
+ // resource context
+ _initResources(pResMgr);
+
+ // clean up: remove context, and delete the resource manager
+ // ( Increment(..) is needed since PopContext() requires that
+ // the file pointer is at the end. )
+ pResMgr->Increment( pResMgr->GetRemainSize() );
+ pResMgr->PopContext();
+ delete pResMgr;
+ }
+
+ // load resources... to be overloaded in sub-classes
+ virtual void _initResources( ResMgr* pMgr ) = 0;
+ };
+
+ class lcl_ReplaceString : public lcl_ResourceString
+ {
+ rtl::OUString m_sDoc_UI;
+ rtl::OUString m_sInstance_UI;
+ rtl::OUString m_sNone_UI;
+
+ rtl::OUString m_sDoc_API;
+ rtl::OUString m_sInstance_API;
+ rtl::OUString m_sNone_API;
+
+ lcl_ReplaceString() :
+ lcl_ResourceString(),
+ m_sDoc_API( RTL_CONSTASCII_USTRINGPARAM("all") ),
+ m_sInstance_API( RTL_CONSTASCII_USTRINGPARAM("instance") ),
+ m_sNone_API( RTL_CONSTASCII_USTRINGPARAM("none") )
+ {
+ init();
+ }
+
+ lcl_ReplaceString( const lcl_ReplaceString& );
+
+ virtual ~lcl_ReplaceString()
+ {
+ }
+
+ // load UI resources from resource file
+ virtual void _initResources( ResMgr * pMgr )
+ {
+ // now, we can access the local resources from the dialog's
+ // resource context
+ m_sDoc_UI = String( ResId( STR_REPLACE_DOC, *pMgr ) );
+ m_sInstance_UI = String( ResId( STR_REPLACE_INST, *pMgr ) );
+ m_sNone_UI = String( ResId( STR_REPLACE_NONE, *pMgr ) );
+ }
+
+ public:
+
+ /** create and obtain the singleton instance */
+ static const lcl_ReplaceString& get()
+ {
+ // keep the singleton instance here
+ static lcl_ReplaceString* m_pInstance = NULL;
+
+ if( m_pInstance == NULL )
+ m_pInstance = new lcl_ReplaceString();
+ return *m_pInstance;
+ }
+
+ /** convert submission replace string from API value to UI value.
+ Use 'none' as default. */
+ rtl::OUString toUI( const rtl::OUString& rStr ) const
+ {
+ if( rStr == m_sDoc_API )
+ return m_sDoc_UI;
+ else if( rStr == m_sInstance_API )
+ return m_sInstance_UI;
+ else
+ return m_sNone_UI;
+ }
+
+ /** convert submission replace string from UI to API.
+ Use 'none' as default. */
+ rtl::OUString toAPI( const rtl::OUString& rStr ) const
+ {
+ if( rStr == m_sDoc_UI )
+ return m_sDoc_API;
+ else if( rStr == m_sInstance_UI )
+ return m_sInstance_API;
+ else
+ return m_sNone_API;
+ }
+ };
+
+ class lcl_MethodString : public lcl_ResourceString
+ {
+ rtl::OUString m_sPost_UI;
+ rtl::OUString m_sPut_UI;
+ rtl::OUString m_sGet_UI;
+
+ rtl::OUString m_sPost_API;
+ rtl::OUString m_sPut_API;
+ rtl::OUString m_sGet_API;
+
+ lcl_MethodString() :
+ lcl_ResourceString(),
+ m_sPost_API( RTL_CONSTASCII_USTRINGPARAM("post") ),
+ m_sPut_API( RTL_CONSTASCII_USTRINGPARAM("put") ),
+ m_sGet_API( RTL_CONSTASCII_USTRINGPARAM("get") )
+ {
+ init();
+ }
+
+ lcl_MethodString( const lcl_MethodString& );
+
+ virtual ~lcl_MethodString()
+ {
+ }
+
+ // load UI resources from resource file
+ virtual void _initResources(ResMgr* pMgr)
+ {
+ m_sPost_UI = String( ResId( STR_METHOD_POST, *pMgr ) );
+ m_sPut_UI = String( ResId( STR_METHOD_PUT, *pMgr ) );
+ m_sGet_UI = String( ResId( STR_METHOD_GET, *pMgr ) );
+ }
+
+ public:
+
+ /** create and obtain the singleton instance */
+ static const lcl_MethodString& get()
+ {
+ // keep the singleton instance here
+ static lcl_MethodString* m_pInstance = NULL;
+
+ if( m_pInstance == NULL )
+ m_pInstance = new lcl_MethodString();
+ return *m_pInstance;
+ }
+
+ /** convert from API to UI; put is default. */
+ rtl::OUString toUI( const rtl::OUString& rStr ) const
+ {
+ if( rStr == m_sGet_API )
+ return m_sGet_UI;
+ else if( rStr == m_sPost_API )
+ return m_sPost_UI;
+ else
+ return m_sPut_UI;
+ }
+
+ /** convert from UI to API; put is default */
+ rtl::OUString toAPI( const rtl::OUString& rStr ) const
+ {
+ if( rStr == m_sGet_UI )
+ return m_sGet_API;
+ else if( rStr == m_sPost_UI )
+ return m_sPost_API;
+ else
+ return m_sPut_API;
+ }
+ };
+
+ //------------------------------------------------------------------------
+ SvLBoxEntry* XFormsPage::AddEntry( const Reference< XPropertySet >& _rEntry )
+ {
+ SvLBoxEntry* pEntry = NULL;
+ const ImageList& rImageList = m_pNaviWin->GetItemImageList();
+ Image aImage = rImageList.GetImage( IID_ELEMENT );
+
+ ItemNode* pNode = new ItemNode( _rEntry );
+ rtl::OUString sTemp;
+
+ if ( DGTSubmission == m_eGroup )
+ {
+ try
+ {
+ // ID
+ _rEntry->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
+ pEntry = m_aItemList.InsertEntry( sTemp, aImage, aImage, NULL, FALSE, LIST_APPEND, pNode );
+ // Action
+ _rEntry->getPropertyValue( PN_SUBMISSION_ACTION ) >>= sTemp;
+ String sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_ACTION );
+ sEntry += String( sTemp );
+ m_aItemList.InsertEntry( sEntry, aImage, aImage, pEntry );
+ // Method
+ _rEntry->getPropertyValue( PN_SUBMISSION_METHOD ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_METHOD );
+ sEntry += String( lcl_MethodString::get().toUI( sTemp ) );
+ m_aItemList.InsertEntry( sEntry, aImage, aImage, pEntry );
+ // Ref
+ _rEntry->getPropertyValue( PN_SUBMISSION_REF ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_REF );
+ sEntry += String( sTemp );
+ m_aItemList.InsertEntry( sEntry, aImage, aImage, pEntry );
+ // Bind
+ _rEntry->getPropertyValue( PN_SUBMISSION_BIND ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_BIND );
+ sEntry += String( sTemp );
+ m_aItemList.InsertEntry( sEntry, aImage, aImage, pEntry );
+ // Replace
+ _rEntry->getPropertyValue( PN_SUBMISSION_REPLACE ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_REPLACE );
+ sEntry += String( lcl_ReplaceString::get().toUI( sTemp ) );
+ m_aItemList.InsertEntry( sEntry, aImage, aImage, pEntry );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::AddEntry(Ref): exception caught" );
+ }
+ }
+ else // then Binding Page
+ {
+ try
+ {
+ String sDelim( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
+ ::rtl::OUString sName;
+ _rEntry->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
+ sName += String( sTemp );
+ sName += sDelim;
+ _rEntry->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
+ sName += String( sTemp );
+ pEntry = m_aItemList.InsertEntry(
+ sName, aImage, aImage, NULL, FALSE, LIST_APPEND, pNode );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::AddEntry(Ref): exception caught" );
+ }
+ }
+
+ return pEntry;
+ }
+
+ //------------------------------------------------------------------------
+ void XFormsPage::EditEntry( const Reference< XPropertySet >& _rEntry )
+ {
+ SvLBoxEntry* pEntry = NULL;
+ rtl::OUString sTemp;
+
+ if ( DGTSubmission == m_eGroup )
+ {
+ try
+ {
+ pEntry = m_aItemList.FirstSelected();
+
+ // #i36262# may be called for submission entry *or* for
+ // submission children. If we don't have any children, we
+ // assume the latter case and use the parent
+ if( m_aItemList.GetEntry( pEntry, 0 ) == NULL )
+ {
+ pEntry = m_aItemList.GetModel()->GetParent( pEntry );
+ }
+
+ _rEntry->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
+ m_aItemList.SetEntryText( pEntry, sTemp );
+
+ _rEntry->getPropertyValue( PN_SUBMISSION_BIND ) >>= sTemp;
+ String sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_BIND );
+ sEntry += String( sTemp );
+ ULONG nPos = 0;
+ SvLBoxEntry* pChild = m_aItemList.GetEntry( pEntry, nPos++ );
+ m_aItemList.SetEntryText( pChild, sEntry );
+ _rEntry->getPropertyValue( PN_SUBMISSION_REF ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_REF );
+ sEntry += String( sTemp );
+ pChild = m_aItemList.GetEntry( pEntry, nPos++ );
+ m_aItemList.SetEntryText( pChild, sEntry );
+ _rEntry->getPropertyValue( PN_SUBMISSION_ACTION ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_ACTION );
+ sEntry += String( sTemp );
+ pChild = m_aItemList.GetEntry( pEntry, nPos++ );
+ m_aItemList.SetEntryText( pChild, sEntry );
+ _rEntry->getPropertyValue( PN_SUBMISSION_METHOD ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_METHOD );
+ sEntry += String( lcl_MethodString::get().toUI( sTemp ) );
+ pChild = m_aItemList.GetEntry( pEntry, nPos++ );
+ m_aItemList.SetEntryText( pChild, sEntry );
+ _rEntry->getPropertyValue( PN_SUBMISSION_REPLACE ) >>= sTemp;
+ sEntry = SVX_RESSTR( RID_STR_DATANAV_SUBM_REPLACE );
+ sEntry += String( lcl_ReplaceString::get().toUI( sTemp ) );
+ pChild = m_aItemList.GetEntry( pEntry, nPos++ );
+ m_aItemList.SetEntryText( pChild, sEntry );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::EditEntry(): exception caught" );
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ bool XFormsPage::RemoveEntry()
+ {
+ bool bRet = false;
+ SvLBoxEntry* pEntry = m_aItemList.FirstSelected();
+ if ( pEntry &&
+ ( DGTInstance != m_eGroup || m_aItemList.GetParent( pEntry ) ) )
+ {
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ DBG_ASSERT( xModel.is(), "XFormsPage::RemoveEntry(): no model" );
+ ItemNode* pNode = static_cast< ItemNode* >( pEntry->GetUserData() );
+ DBG_ASSERT( pNode, "XFormsPage::RemoveEntry(): no node" );
+
+ if ( DGTInstance == m_eGroup )
+ {
+ try
+ {
+ DBG_ASSERT( pNode->m_xNode.is(), "XFormsPage::RemoveEntry(): no XNode" );
+ css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
+ bool bIsElement = ( eChildType == css::xml::dom::NodeType_ELEMENT_NODE );
+ USHORT nResId = bIsElement ? RID_QRY_REMOVE_ELEMENT : RID_QRY_REMOVE_ATTRIBUTE;
+ String sVar = bIsElement ? ELEMENTNAME : ATTRIBUTENAME;
+ QueryBox aQBox( this, SVX_RES( nResId ) );
+ String sMessText = aQBox.GetMessText();
+ sMessText.SearchAndReplace(
+ sVar, m_xUIHelper->getNodeDisplayName( pNode->m_xNode, sal_False ) );
+ aQBox.SetMessText( sMessText );
+ if ( aQBox.Execute() == RET_YES )
+ {
+ SvLBoxEntry* pParent = m_aItemList.GetParent( pEntry );
+ DBG_ASSERT( pParent, "XFormsPage::RemoveEntry(): no parent entry" );
+ ItemNode* pParentNode = static_cast< ItemNode* >( pParent->GetUserData() );
+ DBG_ASSERT( pParentNode && pParentNode->m_xNode.is(), "XFormsPage::RemoveEntry(): no parent XNode" );
+
+ Reference< css::xml::dom::XNode > xPNode;
+ Reference< css::xml::dom::XNode > xNode =
+ pParentNode->m_xNode->removeChild( pNode->m_xNode );
+ if ( xNode.is() )
+ xPNode = xNode->getParentNode();
+ DBG_ASSERT( !xPNode.is(), "XFormsPage::RemoveEntry(): node not removed" );
+ bRet = true;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::RemoveEntry(): exception caught" );
+ }
+ }
+ else
+ {
+ DBG_ASSERT( pNode->m_xPropSet.is(), "XFormsPage::RemoveEntry(): no propset" );
+ bool bSubmission = ( DGTSubmission == m_eGroup );
+ USHORT nResId = bSubmission ? RID_QRY_REMOVE_SUBMISSION : RID_QRY_REMOVE_BINDING;
+ rtl::OUString sProperty = bSubmission ? PN_SUBMISSION_ID : PN_BINDING_ID;
+ String sSearch = bSubmission ? SUBMISSIONNAME : BINDINGNAME;
+ rtl::OUString sName;
+ try
+ {
+ pNode->m_xPropSet->getPropertyValue( sProperty ) >>= sName;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::RemoveEntry(): exception caught" );
+ }
+ QueryBox aQBox( this, SVX_RES( nResId ) );
+ String sMessText = aQBox.GetMessText();
+ sMessText.SearchAndReplace( sSearch, String( sName ) );
+ aQBox.SetMessText( sMessText );
+ if ( aQBox.Execute() == RET_YES )
+ {
+ try
+ {
+ if ( bSubmission )
+ xModel->getSubmissions()->remove( makeAny( pNode->m_xPropSet ) );
+ else // then Binding Page
+ xModel->getBindings()->remove( makeAny( pNode->m_xPropSet ) );
+ bRet = true;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::RemoveEntry(): exception caught" );
+ }
+ }
+ }
+
+ if ( bRet )
+ m_aItemList.RemoveEntry( pEntry );
+ }
+
+ return bRet;
+ }
+
+ //------------------------------------------------------------------------
+ long XFormsPage::Notify( NotifyEvent& rNEvt )
+ {
+ long nHandled = 0;
+
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ USHORT nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
+
+ switch ( nCode )
+ {
+ case KEY_DELETE:
+ nHandled = DoMenuAction( TBI_ITEM_REMOVE );
+ break;
+ }
+ }
+
+ return nHandled ? nHandled : Window::Notify( rNEvt );
+ }
+ //------------------------------------------------------------------------
+ void XFormsPage::Resize()
+ {
+ Size aSize = GetOutputSizePixel();
+ Size aTbxSize = m_aToolBox.GetSizePixel();
+ aTbxSize.Width() = aSize.Width();
+ m_aToolBox.SetSizePixel( aTbxSize );
+ aSize.Width() -= 4;
+ aSize.Height() -= ( 4 + aTbxSize.Height() );
+ m_aItemList.SetPosSizePixel( Point( 2, 2 + aTbxSize.Height() ), aSize );
+ }
+ //------------------------------------------------------------------------
+ String XFormsPage::SetModel( const Reference< css::xforms::XModel >& _xModel, USHORT _nPagePos )
+ {
+ DBG_ASSERT( _xModel.is(), "XFormsPage::SetModel(): invalid model" );
+
+ m_xUIHelper = Reference< css::xforms::XFormsUIHelper1 >( _xModel, UNO_QUERY );
+ String sRet;
+ m_bHasModel = true;
+ const ImageList& rImageList = m_pNaviWin->GetItemImageList();
+
+ switch ( m_eGroup )
+ {
+ case DGTInstance :
+ {
+ DBG_ASSERT( _nPagePos != TAB_PAGE_NOTFOUND, "XFormsPage::SetModel(): invalid page position" );
+ try
+ {
+ Reference< XContainer > xContainer( _xModel->getInstances(), UNO_QUERY );
+ if ( xContainer.is() )
+ m_pNaviWin->AddContainerBroadcaster( xContainer );
+
+ Reference< XEnumerationAccess > xNumAccess( _xModel->getInstances(), UNO_QUERY );
+ if ( xNumAccess.is() )
+ {
+ Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
+ if ( xNum.is() && xNum->hasMoreElements() )
+ {
+ USHORT nIter = 0;
+ while ( xNum->hasMoreElements() )
+ {
+ if ( nIter == _nPagePos )
+ {
+ Sequence< PropertyValue > xPropSeq;
+ Any aAny = xNum->nextElement();
+ if ( aAny >>= xPropSeq )
+ sRet = LoadInstance( xPropSeq, rImageList );
+ else
+ {
+ DBG_ERRORFILE( "XFormsPage::SetModel(): invalid instance" );
+ }
+ break;
+ }
+ else
+ {
+ xNum->nextElement();
+ nIter++;
+ }
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::SetModel(): exception caught" );
+ }
+ break;
+ }
+
+ case DGTSubmission :
+ {
+ DBG_ASSERT( TAB_PAGE_NOTFOUND == _nPagePos, "XFormsPage::SetModel(): invalid page position" );
+ try
+ {
+ Reference< XContainer > xContainer( _xModel->getSubmissions(), UNO_QUERY );
+ if ( xContainer.is() )
+ m_pNaviWin->AddContainerBroadcaster( xContainer );
+
+ Reference< XEnumerationAccess > xNumAccess( _xModel->getSubmissions(), UNO_QUERY );
+ if ( xNumAccess.is() )
+ {
+ Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
+ if ( xNum.is() && xNum->hasMoreElements() )
+ {
+ while ( xNum->hasMoreElements() )
+ {
+ Reference< XPropertySet > xPropSet;
+ Any aAny = xNum->nextElement();
+ if ( aAny >>= xPropSet )
+ AddEntry( xPropSet );
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::SetModel(): exception caught" );
+ }
+ break;
+ }
+
+ case DGTBinding :
+ {
+ DBG_ASSERT( TAB_PAGE_NOTFOUND == _nPagePos, "XFormsPage::SetModel(): invalid page position" );
+ try
+ {
+ Reference< XContainer > xContainer( _xModel->getBindings(), UNO_QUERY );
+ if ( xContainer.is() )
+ m_pNaviWin->AddContainerBroadcaster( xContainer );
+
+ Reference< XEnumerationAccess > xNumAccess( _xModel->getBindings(), UNO_QUERY );
+ if ( xNumAccess.is() )
+ {
+ Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
+ if ( xNum.is() && xNum->hasMoreElements() )
+ {
+ Image aImage1 = rImageList.GetImage( IID_ELEMENT );
+ Image aImage2 = rImageList.GetImage( IID_ELEMENT );
+ String sDelim( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
+ while ( xNum->hasMoreElements() )
+ {
+ Reference< XPropertySet > xPropSet;
+ Any aAny = xNum->nextElement();
+ if ( aAny >>= xPropSet )
+ {
+ String sEntry;
+ rtl::OUString sTemp;
+ xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
+ sEntry += String( sTemp );
+ sEntry += sDelim;
+ xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
+ sEntry += String( sTemp );
+
+ ItemNode* pNode = new ItemNode( xPropSet );
+ m_aItemList.InsertEntry(
+ sEntry, aImage1, aImage2, NULL, FALSE, LIST_APPEND, pNode );
+ }
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::SetModel(): exception caught" );
+ }
+ break;
+ }
+ default:
+ DBG_ERROR( "XFormsPage::SetModel: unknown group!" );
+ break;
+ }
+
+ EnableMenuItems( NULL );
+
+ return sRet;
+ }
+ //------------------------------------------------------------------------
+ void XFormsPage::ClearModel()
+ {
+ m_bHasModel = false;
+ m_aItemList.DeleteAndClear();
+ }
+ //------------------------------------------------------------------------
+ String XFormsPage::LoadInstance(
+ const Sequence< PropertyValue >& _xPropSeq, const ImageList& _rImgLst )
+ {
+ String sRet;
+ rtl::OUString sTemp;
+ rtl::OUString sInstModel = PN_INSTANCE_MODEL;
+ rtl::OUString sInstName = PN_INSTANCE_ID;
+ rtl::OUString sInstURL = PN_INSTANCE_URL;
+ const PropertyValue* pProps = _xPropSeq.getConstArray();
+ const PropertyValue* pPropsEnd = pProps + _xPropSeq.getLength();
+ for ( ; pProps != pPropsEnd; ++pProps )
+ {
+ if ( sInstModel.compareTo( pProps->Name ) == 0 )
+ {
+ Reference< css::xml::dom::XNode > xRoot;
+ if ( pProps->Value >>= xRoot )
+ {
+ try
+ {
+ Reference< XEventTarget > xTarget( xRoot, UNO_QUERY );
+ if ( xTarget.is() )
+ m_pNaviWin->AddEventBroadcaster( xTarget );
+
+ #if OSL_DEBUG_LEVEL > 0
+ css::xml::dom::NodeType eNodeType = xRoot->getNodeType(); (void)eNodeType;
+ #endif
+ ::rtl::OUString sNodeName =
+ m_xUIHelper->getNodeDisplayName( xRoot, m_pNaviWin->IsShowDetails() );
+ if ( sNodeName.getLength() == 0 )
+ sNodeName = xRoot->getNodeName();
+ if ( xRoot->hasChildNodes() )
+ AddChildren( NULL, _rImgLst, xRoot );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::LoadInstance(): exception caught" );
+ }
+ }
+ }
+ else if ( sInstName.compareTo( pProps->Name ) == 0 && ( pProps->Value >>= sTemp ) )
+ m_sInstanceName = sRet = sTemp;
+ else if ( sInstURL.compareTo( pProps->Name ) == 0 && ( pProps->Value >>= sTemp ) )
+ m_sInstanceURL = sTemp;
+ }
+
+ return sRet;
+ }
+
+ //------------------------------------------------------------------------
+ bool XFormsPage::DoMenuAction( USHORT _nMenuID )
+ {
+ return DoToolBoxAction( _nMenuID );
+ }
+
+ //------------------------------------------------------------------------
+ void XFormsPage::EnableMenuItems( Menu* _pMenu )
+ {
+ BOOL bEnableAdd = FALSE;
+ BOOL bEnableEdit = FALSE;
+ BOOL bEnableRemove = FALSE;
+
+ SvLBoxEntry* pEntry = m_aItemList.FirstSelected();
+ if ( pEntry )
+ {
+ bEnableAdd = TRUE;
+ bool bSubmitChild = false;
+ if ( DGTSubmission == m_eGroup && m_aItemList.GetParent( pEntry ) )
+ {
+ pEntry = m_aItemList.GetParent( pEntry );
+ bSubmitChild = true;
+ }
+ ItemNode* pNode = static_cast< ItemNode* >( pEntry->GetUserData() );
+ if ( pNode && ( pNode->m_xNode.is() || pNode->m_xPropSet.is() ) )
+ {
+ bEnableEdit = TRUE;
+ bEnableRemove = ( bSubmitChild != true );
+ if ( DGTInstance == m_eGroup && !m_aItemList.GetParent( pEntry ) )
+ bEnableRemove = FALSE;
+ if ( pNode->m_xNode.is() )
+ {
+ try
+ {
+ css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
+ if ( eChildType != css::xml::dom::NodeType_ELEMENT_NODE
+ && eChildType != css::xml::dom::NodeType_DOCUMENT_NODE )
+ {
+ bEnableAdd = FALSE;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::EnableMenuItems(): exception caught" );
+ }
+ }
+ }
+ }
+ else if ( m_eGroup != DGTInstance )
+ bEnableAdd = TRUE;
+
+ m_aToolBox.EnableItem( TBI_ITEM_ADD, bEnableAdd );
+ m_aToolBox.EnableItem( TBI_ITEM_ADD_ELEMENT, bEnableAdd );
+ m_aToolBox.EnableItem( TBI_ITEM_ADD_ATTRIBUTE, bEnableAdd );
+ m_aToolBox.EnableItem( TBI_ITEM_EDIT, bEnableEdit );
+ m_aToolBox.EnableItem( TBI_ITEM_REMOVE, bEnableRemove );
+
+ if ( _pMenu )
+ {
+ _pMenu->EnableItem( TBI_ITEM_ADD, bEnableAdd );
+ _pMenu->EnableItem( TBI_ITEM_ADD_ELEMENT, bEnableAdd );
+ _pMenu->EnableItem( TBI_ITEM_ADD_ATTRIBUTE, bEnableAdd );
+ _pMenu->EnableItem( TBI_ITEM_EDIT, bEnableEdit );
+ _pMenu->EnableItem( TBI_ITEM_REMOVE, bEnableRemove );
+ }
+ if ( DGTInstance == m_eGroup )
+ {
+ USHORT nResId1 = RID_STR_DATANAV_EDIT_ELEMENT;
+ USHORT nResId2 = RID_STR_DATANAV_REMOVE_ELEMENT;
+ if ( pEntry )
+ {
+ ItemNode* pNode = static_cast< ItemNode* >( pEntry->GetUserData() );
+ if ( pNode && pNode->m_xNode.is() )
+ {
+ try
+ {
+ css::xml::dom::NodeType eChildType = pNode->m_xNode->getNodeType();
+ if ( eChildType == css::xml::dom::NodeType_ATTRIBUTE_NODE )
+ {
+ nResId1 = RID_STR_DATANAV_EDIT_ATTRIBUTE;
+ nResId2 = RID_STR_DATANAV_REMOVE_ATTRIBUTE;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "XFormsPage::EnableMenuItems(): exception caught" );
+ }
+ }
+ }
+ m_aToolBox.SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( nResId1 ) );
+ m_aToolBox.SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( nResId2 ) );
+ if ( _pMenu )
+ {
+ _pMenu->SetItemText( TBI_ITEM_EDIT, SVX_RESSTR( nResId1 ) );
+ _pMenu->SetItemText( TBI_ITEM_REMOVE, SVX_RESSTR( nResId2 ) );
+ }
+ }
+ }
+
+
+ //========================================================================
+ // class DataNavigatorWindow
+ //========================================================================
+ DataNavigatorWindow::DataNavigatorWindow( Window* pParent, SfxBindings* pBindings ) :
+
+ Window( pParent, SVX_RES( RID_SVXWIN_DATANAVIGATOR ) ),
+
+ m_aModelsBox ( this, SVX_RES( LB_MODELS ) ),
+ m_aModelBtn ( this, SVX_RES( MB_MODELS ) ),
+ m_aTabCtrl ( this, SVX_RES( TC_ITEMS ) ),
+ m_aInstanceBtn ( this, SVX_RES( MB_INSTANCES ) ),
+
+ m_pInstPage ( NULL ),
+ m_pSubmissionPage ( NULL ),
+ m_pBindingPage ( NULL ),
+
+ m_nMinWidth ( 0 ),
+ m_nMinHeight ( 0 ),
+ m_nBorderHeight ( 0 ),
+ m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
+ m_bShowDetails ( false ),
+ m_bIsNotifyDisabled ( false ),
+
+ m_aItemImageList ( SVX_RES( IL_ITEM_BMPS ) ),
+ m_xDataListener ( new DataListener( this ) )
+
+ {
+ FreeResource();
+
+ // init minimal metric
+ m_a2Size = LogicToPixel( Size( 2, 2 ), MAP_APPFONT );
+ m_a3Size = LogicToPixel( Size( 3, 3 ), MAP_APPFONT );
+ Size aOutSz = GetOutputSizePixel();
+ Size aLogSize = PixelToLogic( aOutSz, MAP_APPFONT );
+ m_nMinWidth = aLogSize.Width();
+ m_nMinHeight = aLogSize.Height();
+ m_nBorderHeight = 4*m_a3Size.Height() +
+ m_aModelBtn.GetSizePixel().Height() + m_aInstanceBtn.GetSizePixel().Height();
+
+ // handler
+ m_aModelsBox.SetSelectHdl( LINK( this, DataNavigatorWindow, ModelSelectHdl ) );
+ Link aLink = LINK( this, DataNavigatorWindow, MenuSelectHdl );
+ m_aModelBtn.SetSelectHdl( aLink );
+ m_aInstanceBtn.SetSelectHdl( aLink );
+ aLink = LINK( this, DataNavigatorWindow, MenuActivateHdl );
+ m_aModelBtn.SetActivateHdl( aLink );
+ m_aInstanceBtn.SetActivateHdl( aLink );
+ m_aTabCtrl.SetActivatePageHdl( LINK( this, DataNavigatorWindow, ActivatePageHdl ) );
+ m_aUpdateTimer.SetTimeout( 2000 );
+ m_aUpdateTimer.SetTimeoutHdl( LINK( this, DataNavigatorWindow, UpdateHdl ) );
+
+ // init tabcontrol
+ m_aTabCtrl.Show();
+ sal_Int32 nPageId = TID_INSTANCE;
+ SvtViewOptions aViewOpt( E_TABDIALOG, CFGNAME_DATANAVIGATOR );
+ if ( aViewOpt.Exists() )
+ {
+ nPageId = aViewOpt.GetPageID();
+ aViewOpt.GetUserItem(CFGNAME_SHOWDETAILS) >>= m_bShowDetails;
+ }
+
+ Menu* pMenu = m_aInstanceBtn.GetPopupMenu();
+ pMenu->SetItemBits( MID_SHOW_DETAILS, MIB_CHECKABLE );
+ pMenu->CheckItem( MID_SHOW_DETAILS, m_bShowDetails );
+
+ m_aTabCtrl.SetCurPageId( static_cast< USHORT >( nPageId ) );
+ ActivatePageHdl( &m_aTabCtrl );
+
+ // get our frame
+ DBG_ASSERT( pBindings != NULL,
+ "DataNavigatorWindow::LoadModels(): no SfxBindings; can't get frame" );
+ m_xFrame = Reference<XFrame>(
+ pBindings->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface(),
+ UNO_QUERY );
+ DBG_ASSERT( m_xFrame.is(), "DataNavigatorWindow::LoadModels(): no frame" );
+ // add frameaction listener
+ Reference< XFrameActionListener > xListener(
+ static_cast< XFrameActionListener* >( m_xDataListener.get() ), UNO_QUERY );
+ m_xFrame->addFrameActionListener( xListener );
+
+ // load xforms models of the current document
+ LoadModels();
+ }
+ //------------------------------------------------------------------------
+ DataNavigatorWindow::~DataNavigatorWindow()
+ {
+ SvtViewOptions aViewOpt( E_TABDIALOG, CFGNAME_DATANAVIGATOR );
+ aViewOpt.SetPageID( static_cast< sal_Int32 >( m_aTabCtrl.GetCurPageId() ) );
+ Any aAny;
+ aAny <<= m_bShowDetails;
+ aViewOpt.SetUserItem(CFGNAME_SHOWDETAILS,aAny);
+
+ delete m_pInstPage;
+ delete m_pSubmissionPage;
+ delete m_pBindingPage;
+
+ sal_Int32 i, nCount = m_aPageList.size();
+ for ( i = 0; i < nCount; ++i )
+ delete m_aPageList[i];
+ Reference< XFrameActionListener > xListener(
+ static_cast< XFrameActionListener* >( m_xDataListener.get() ), UNO_QUERY );
+ m_xFrame->removeFrameActionListener( xListener );
+ RemoveBroadcaster();
+ m_xDataListener.clear();
+ }
+
+ // -----------------------------------------------------------------------
+ IMPL_LINK( DataNavigatorWindow, ModelSelectHdl, ListBox *, pBox )
+ {
+ USHORT nPos = m_aModelsBox.GetSelectEntryPos();
+ // pBox == NULL, if you want to force a new fill.
+ if ( nPos != m_nLastSelectedPos || !pBox )
+ {
+ m_nLastSelectedPos = nPos;
+ ClearAllPageModels( pBox != NULL );
+ InitPages();
+ SetPageModel();
+ }
+
+ return 0;
+ }
+ // -----------------------------------------------------------------------
+ IMPL_LINK( DataNavigatorWindow, MenuSelectHdl, MenuButton *, pBtn )
+ {
+ bool bIsDocModified = false;
+ Reference< css::xforms::XFormsUIHelper1 > xUIHelper;
+ USHORT nSelectedPos = m_aModelsBox.GetSelectEntryPos();
+ ::rtl::OUString sSelectedModel( m_aModelsBox.GetEntry( nSelectedPos ) );
+ Reference< css::xforms::XModel > xModel;
+ try
+ {
+ Any aAny = m_xDataContainer->getByName( sSelectedModel );
+ if ( aAny >>= xModel )
+ xUIHelper = Reference< css::xforms::XFormsUIHelper1 >( xModel, UNO_QUERY );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ DBG_ASSERT( xUIHelper.is(), "DataNavigatorWindow::MenuSelectHdl(): no UIHelper" );
+
+ m_bIsNotifyDisabled = true;
+
+ if ( &m_aModelBtn == pBtn )
+ {
+ switch ( pBtn->GetCurItemId() )
+ {
+ case MID_MODELS_ADD :
+ {
+ AddModelDialog aDlg( this, false );
+ bool bShowDialog = true;
+ while ( bShowDialog )
+ {
+ bShowDialog = false;
+ if ( aDlg.Execute() == RET_OK )
+ {
+ String sNewName = aDlg.GetName();
+ sal_Bool bDocumentData = aDlg.GetModifyDoc();
+
+ if ( m_aModelsBox.GetEntryPos( sNewName ) != LISTBOX_ENTRY_NOTFOUND )
+ {
+ // error: model name already exists
+ ErrorBox aErrBox( this, SVX_RES( RID_ERR_DOUBLE_MODELNAME ) );
+ String sMessText = aErrBox.GetMessText();
+ sMessText.SearchAndReplace( MSG_VARIABLE, sNewName );
+ aErrBox.SetMessText( sMessText );
+ aErrBox.Execute();
+ bShowDialog = true;
+ }
+ else
+ {
+ try
+ {
+ // add new model to frame model
+ Reference< css::xforms::XModel > xNewModel(
+ xUIHelper->newModel( m_xFrameModel, sNewName ), UNO_SET_THROW );
+
+ Reference< XPropertySet > xModelProps( xNewModel, UNO_QUERY_THROW );
+ xModelProps->setPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ),
+ makeAny( sal_Bool( !bDocumentData ) ) );
+
+ USHORT nNewPos = m_aModelsBox.InsertEntry( sNewName );
+ m_aModelsBox.SelectEntryPos( nNewPos );
+ ModelSelectHdl( &m_aModelsBox );
+ bIsDocModified = true;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ }
+ }
+ }
+ break;
+ }
+ case MID_MODELS_EDIT :
+ {
+ AddModelDialog aDlg( this, true );
+ aDlg.SetName( sSelectedModel );
+
+ bool bDocumentData( false );
+ try
+ {
+ Reference< css::xforms::XFormsSupplier > xFormsSupp( m_xFrameModel, UNO_QUERY_THROW );
+ Reference< XNameContainer > xXForms( xFormsSupp->getXForms(), UNO_SET_THROW );
+ Reference< XPropertySet > xModelProps( xXForms->getByName( sSelectedModel ), UNO_QUERY_THROW );
+ sal_Bool bExternalData = sal_False;
+ OSL_VERIFY( xModelProps->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ) ) >>= bExternalData );
+ bDocumentData = ( bExternalData == sal_False );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ aDlg.SetModifyDoc( bDocumentData );
+
+ if ( aDlg.Execute() == RET_OK )
+ {
+ if ( aDlg.GetModifyDoc() != bool( bDocumentData ) )
+ {
+ bDocumentData = aDlg.GetModifyDoc();
+ try
+ {
+ Reference< css::xforms::XFormsSupplier > xFormsSupp( m_xFrameModel, UNO_QUERY_THROW );
+ Reference< XNameContainer > xXForms( xFormsSupp->getXForms(), UNO_SET_THROW );
+ Reference< XPropertySet > xModelProps( xXForms->getByName( sSelectedModel ), UNO_QUERY_THROW );
+ xModelProps->setPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ),
+ makeAny( sal_Bool( !bDocumentData ) ) );
+ bIsDocModified = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ String sNewName = aDlg.GetName();
+ if ( sNewName.Len() > 0 && ( sNewName != String( sSelectedModel ) ) )
+ {
+ try
+ {
+ xUIHelper->renameModel( m_xFrameModel, sSelectedModel, sNewName );
+
+ m_aModelsBox.RemoveEntry( nSelectedPos );
+ nSelectedPos = m_aModelsBox.InsertEntry( sNewName );
+ m_aModelsBox.SelectEntryPos( nSelectedPos );
+ bIsDocModified = true;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ }
+ }
+ break;
+ }
+ case MID_MODELS_REMOVE :
+ {
+ QueryBox aQBox( this, SVX_RES( RID_QRY_REMOVE_MODEL ) );
+ String sText = aQBox.GetMessText();
+ sText.SearchAndReplace( MODELNAME, sSelectedModel );
+ aQBox.SetMessText( sText );
+ if ( aQBox.Execute() == RET_YES )
+ {
+ try
+ {
+ xUIHelper->removeModel( m_xFrameModel, sSelectedModel );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ m_aModelsBox.RemoveEntry( nSelectedPos );
+ if ( m_aModelsBox.GetEntryCount() <= nSelectedPos )
+ nSelectedPos = m_aModelsBox.GetEntryCount() - 1;
+ m_aModelsBox.SelectEntryPos( nSelectedPos );
+ ModelSelectHdl( &m_aModelsBox );
+ bIsDocModified = true;
+ }
+ break;
+ }
+ default:
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): wrong menu item" );
+ }
+ }
+ }
+ else if ( &m_aInstanceBtn == pBtn )
+ {
+ switch ( pBtn->GetCurItemId() )
+ {
+ case MID_INSTANCES_ADD :
+ {
+ AddInstanceDialog aDlg( this, false );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ USHORT nInst = GetNewPageId();
+ ::rtl::OUString sName = aDlg.GetName();
+ ::rtl::OUString sURL = aDlg.GetURL();
+ bool bLinkOnce = aDlg.IsLinkInstance();
+ try
+ {
+ Reference< css::xml::dom::XDocument > xNewInst =
+ xUIHelper->newInstance( sName, sURL, !bLinkOnce );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ ModelSelectHdl( NULL );
+ m_aTabCtrl.SetCurPageId( nInst );
+ XFormsPage* pPage = GetCurrentPage( nInst );
+ pPage->SetInstanceName(sName);
+ pPage->SetInstanceURL(sURL);
+ pPage->SetLinkOnce(bLinkOnce);
+ ActivatePageHdl( &m_aTabCtrl );
+ bIsDocModified = true;
+ }
+ break;
+ }
+ case MID_INSTANCES_EDIT :
+ {
+ USHORT nId = 0;
+ XFormsPage* pPage = GetCurrentPage( nId );
+ if ( pPage )
+ {
+ AddInstanceDialog aDlg( this, true );
+ aDlg.SetName( pPage->GetInstanceName() );
+ aDlg.SetURL( pPage->GetInstanceURL() );
+ aDlg.SetLinkInstance( pPage->GetLinkOnce() );
+ String sOldName = aDlg.GetName();
+ if ( aDlg.Execute() == RET_OK )
+ {
+ String sNewName = aDlg.GetName();
+ ::rtl::OUString sURL = aDlg.GetURL();
+ bool bLinkOnce = aDlg.IsLinkInstance();
+ try
+ {
+ xUIHelper->renameInstance( sOldName,
+ sNewName,
+ sURL,
+ !bLinkOnce );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ pPage->SetInstanceName(sNewName);
+ pPage->SetInstanceURL(sURL);
+ pPage->SetLinkOnce(bLinkOnce);
+ m_aTabCtrl.SetPageText( nId, sNewName );
+ bIsDocModified = true;
+ }
+ delete(pPage);
+ }
+ break;
+ }
+ case MID_INSTANCES_REMOVE :
+ {
+ USHORT nId = 0;
+ XFormsPage* pPage = GetCurrentPage( nId );
+ if ( pPage )
+ {
+ String sInstName = pPage->GetInstanceName();
+ QueryBox aQBox( this, SVX_RES( RID_QRY_REMOVE_INSTANCE ) );
+ String sMessText = aQBox.GetMessText();
+ sMessText.SearchAndReplace( INSTANCENAME, sInstName );
+ aQBox.SetMessText( sMessText );
+ if ( aQBox.Execute() == RET_YES )
+ {
+ bool bDoRemove = false;
+ if ( nId > TID_INSTANCE )
+ {
+ PageList::iterator aPageListEnd = m_aPageList.end();
+ PageList::iterator aFoundPage =
+ std::find( m_aPageList.begin(), aPageListEnd, pPage );
+ if ( aFoundPage != aPageListEnd )
+ {
+ m_aPageList.erase( aFoundPage );
+ delete pPage;
+ bDoRemove = true;
+ }
+ }
+ else
+ {
+ DELETEZ( m_pInstPage );
+ bDoRemove = true;
+ }
+
+ if ( bDoRemove )
+ {
+ try
+ {
+ xUIHelper->removeInstance( sInstName );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): exception caught" );
+ }
+ m_aTabCtrl.RemovePage( nId );
+ m_aTabCtrl.SetCurPageId( TID_INSTANCE );
+ ModelSelectHdl( NULL );
+ bIsDocModified = true;
+ }
+ }
+ }
+ break;
+ }
+ case MID_SHOW_DETAILS :
+ {
+ m_bShowDetails = !m_bShowDetails;
+ m_aInstanceBtn.GetPopupMenu()->CheckItem( MID_SHOW_DETAILS, m_bShowDetails );
+ ModelSelectHdl( &m_aModelsBox );
+ break;
+ }
+ default:
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): wrong menu item" );
+ }
+ }
+ }
+ else
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuSelectHdl(): wrong button" );
+ }
+
+ m_bIsNotifyDisabled = false;
+
+ if ( bIsDocModified )
+ SetDocModified();
+ return 0;
+ }
+ // -----------------------------------------------------------------------
+ IMPL_LINK( DataNavigatorWindow, MenuActivateHdl, MenuButton *, pBtn )
+ {
+ Menu* pMenu = pBtn->GetPopupMenu();
+
+ if ( &m_aInstanceBtn == pBtn )
+ {
+ bool bIsInstPage = ( m_aTabCtrl.GetCurPageId() >= TID_INSTANCE );
+ pMenu->EnableItem( MID_INSTANCES_EDIT, bIsInstPage );
+ pMenu->EnableItem( MID_INSTANCES_REMOVE,
+ bIsInstPage && m_aTabCtrl.GetPageCount() > MIN_PAGE_COUNT );
+ pMenu->EnableItem( MID_SHOW_DETAILS, bIsInstPage );
+ }
+ else if ( &m_aModelBtn == pBtn )
+ {
+ // we need at least one model!
+ pMenu->EnableItem( MID_MODELS_REMOVE, m_aModelsBox.GetEntryCount() > 1 );
+ }
+ else
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::MenuActivateHdl(): wrong button" );
+ }
+ return 0;
+ }
+ // -----------------------------------------------------------------------
+ IMPL_LINK( DataNavigatorWindow, ActivatePageHdl, TabControl *, EMPTYARG )
+ {
+ USHORT nId = 0;
+ XFormsPage* pPage = GetCurrentPage( nId );
+ if ( pPage )
+ {
+ m_aTabCtrl.SetTabPage( nId, pPage );
+ if ( m_xDataContainer.is() && !pPage->HasModel() )
+ SetPageModel();
+ }
+
+ return 0;
+ }
+ // -----------------------------------------------------------------------
+ IMPL_LINK( DataNavigatorWindow, UpdateHdl, Timer *, EMPTYARG )
+ {
+ ModelSelectHdl( NULL );
+ return 0;
+ }
+ // -----------------------------------------------------------------------
+ XFormsPage* DataNavigatorWindow::GetCurrentPage( USHORT& rCurId )
+ {
+ rCurId = m_aTabCtrl.GetCurPageId();
+ XFormsPage* pPage = NULL;
+ switch ( rCurId )
+ {
+ case TID_SUBMISSION:
+ {
+ if ( !m_pSubmissionPage )
+ m_pSubmissionPage = new XFormsPage( &m_aTabCtrl, this, DGTSubmission );
+ pPage = m_pSubmissionPage;
+ break;
+ }
+
+ case TID_BINDINGS:
+ {
+ if ( !m_pBindingPage )
+ m_pBindingPage = new XFormsPage( &m_aTabCtrl, this, DGTBinding );
+ pPage = m_pBindingPage;
+ break;
+ }
+
+ case TID_INSTANCE:
+ {
+ if ( !m_pInstPage )
+ m_pInstPage = new XFormsPage( &m_aTabCtrl, this, DGTInstance );
+ pPage = m_pInstPage;
+ break;
+ }
+ }
+
+ if ( rCurId > TID_INSTANCE )
+ {
+ USHORT nPos = m_aTabCtrl.GetPagePos( rCurId );
+ if ( HasFirstInstancePage() && nPos > 0 )
+ nPos--;
+ if ( m_aPageList.size() > nPos )
+ pPage = m_aPageList[nPos];
+ else
+ {
+ pPage = new XFormsPage( &m_aTabCtrl, this, DGTInstance );
+ m_aPageList.push_back( pPage );
+ }
+ }
+
+ return pPage;
+ }
+ // -----------------------------------------------------------------------
+ void DataNavigatorWindow::LoadModels()
+ {
+ if ( !m_xFrameModel.is() )
+ {
+ // get model of active frame
+ Reference< XController > xCtrl = m_xFrame->getController();
+ if ( xCtrl.is() )
+ {
+ try
+ {
+ m_xFrameModel = xCtrl->getModel();
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::LoadModels(): exception caught" );
+ }
+ }
+ }
+
+ if ( m_xFrameModel.is() )
+ {
+ try
+ {
+ ::rtl::OUString sURL = m_xFrameModel->getURL();
+ Reference< css::xforms::XFormsSupplier > xFormsSupp( m_xFrameModel, UNO_QUERY );
+ if ( xFormsSupp.is() )
+ {
+ Reference< XNameContainer > xContainer = xFormsSupp->getXForms();
+ if ( xContainer.is() )
+ {
+ m_xDataContainer = xContainer;
+ Sequence< ::rtl::OUString > aNameList = m_xDataContainer->getElementNames();
+ sal_Int32 i, nCount = aNameList.getLength();
+ ::rtl::OUString* pNames = aNameList.getArray();
+ for ( i = 0; i < nCount; ++i )
+ {
+ Any aAny = m_xDataContainer->getByName( pNames[i] );
+ Reference< css::xforms::XModel > xFormsModel;
+ if ( aAny >>= xFormsModel )
+ m_aModelsBox.InsertEntry( xFormsModel->getID() );
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::LoadModels(): exception caught" );
+ }
+ }
+
+ if ( m_aModelsBox.GetEntryCount() > 0 )
+ {
+ m_aModelsBox.SelectEntryPos(0);
+ ModelSelectHdl( &m_aModelsBox );
+ }
+ }
+ // -----------------------------------------------------------------------
+ void DataNavigatorWindow::SetPageModel()
+ {
+ rtl::OUString sModel( m_aModelsBox.GetSelectEntry() );
+ try
+ {
+ Any aAny = m_xDataContainer->getByName( sModel );
+ Reference< css::xforms::XModel > xFormsModel;
+ if ( aAny >>= xFormsModel )
+ {
+ USHORT nPagePos = TAB_PAGE_NOTFOUND;
+ USHORT nId = 0;
+ XFormsPage* pPage = GetCurrentPage( nId );
+ DBG_ASSERT( pPage, "DataNavigatorWindow::SetPageModel(): no page" );
+ if ( nId >= TID_INSTANCE )
+ // instance page
+ nPagePos = m_aTabCtrl.GetPagePos( nId );
+ m_bIsNotifyDisabled = true;
+ String sText = pPage->SetModel( xFormsModel, nPagePos );
+ m_bIsNotifyDisabled = false;
+ if ( sText.Len() > 0 )
+ m_aTabCtrl.SetPageText( nId, sText );
+ }
+ }
+ catch ( NoSuchElementException& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::SetPageModel(): no such element" );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::SetPageModel(): unexpected exception" );
+ }
+ }
+ // -----------------------------------------------------------------------
+ void DataNavigatorWindow::InitPages()
+ {
+ rtl::OUString sModel( m_aModelsBox.GetSelectEntry() );
+ try
+ {
+ Any aAny = m_xDataContainer->getByName( sModel );
+ Reference< css::xforms::XModel > xModel;
+ if ( aAny >>= xModel )
+ {
+ Reference< XEnumerationAccess > xNumAccess( xModel->getInstances(), UNO_QUERY );
+ if ( xNumAccess.is() )
+ {
+ Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
+ if ( xNum.is() && xNum->hasMoreElements() )
+ {
+ sal_Int32 nAlreadyLoadedCount = m_aPageList.size();
+ if ( !HasFirstInstancePage() && nAlreadyLoadedCount > 0 )
+ nAlreadyLoadedCount--;
+ sal_Int32 nIdx = 0;
+ while ( xNum->hasMoreElements() )
+ {
+ if ( nIdx > nAlreadyLoadedCount )
+ {
+ Sequence< PropertyValue > xPropSeq;
+ if ( xNum->nextElement() >>= xPropSeq )
+ CreateInstancePage( xPropSeq );
+ else
+ {
+ DBG_ERRORFILE( "DataNavigator::InitPages(): invalid instance" );
+ }
+ }
+ else
+ xNum->nextElement();
+ nIdx++;
+ }
+ }
+ }
+ }
+ }
+ catch ( NoSuchElementException& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::SetPageModel(): no such element" );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::SetPageModel(): unexpected exception" );
+ }
+ }
+ // -----------------------------------------------------------------------
+ void DataNavigatorWindow::ClearAllPageModels( bool bClearPages )
+ {
+ if ( m_pInstPage )
+ m_pInstPage->ClearModel();
+ if ( m_pSubmissionPage )
+ m_pSubmissionPage->ClearModel();
+ if ( m_pBindingPage )
+ m_pBindingPage->ClearModel();
+
+ sal_Int32 i, nCount = m_aPageList.size();
+ for ( i = 0; i < nCount; ++i )
+ {
+ XFormsPage* pPage = m_aPageList[i];
+ pPage->ClearModel();
+ if ( bClearPages )
+ delete pPage;
+ }
+
+ if ( bClearPages )
+ {
+ m_aPageList.clear();
+ while ( m_aTabCtrl.GetPageCount() > MIN_PAGE_COUNT )
+ m_aTabCtrl.RemovePage( m_aTabCtrl.GetPageId( 1 ) );
+ }
+ }
+ // -----------------------------------------------------------------------
+ void DataNavigatorWindow::CreateInstancePage( const Sequence< PropertyValue >& _xPropSeq )
+ {
+ rtl::OUString sInstName;
+ rtl::OUString sID( PN_INSTANCE_ID );
+ const PropertyValue* pProps = _xPropSeq.getConstArray();
+ const PropertyValue* pPropsEnd = pProps + _xPropSeq.getLength();
+ for ( ; pProps != pPropsEnd; ++pProps )
+ {
+ if ( sID.compareTo( pProps->Name ) == 0 )
+ {
+ pProps->Value >>= sInstName;
+ break;
+ }
+ }
+
+ USHORT nPageId = GetNewPageId();
+ if ( sInstName.getLength() == 0 )
+ {
+ DBG_ERRORFILE( "DataNavigatorWindow::CreateInstancePage(): instance without name" );
+ String sTemp = String::CreateFromAscii( "untitled" );
+ sTemp += String::CreateFromInt32( nPageId );
+ sInstName = sTemp;
+ }
+ m_aTabCtrl.InsertPage( nPageId, sInstName, m_aTabCtrl.GetPageCount() - 2 );
+ }
+
+ //------------------------------------------------------------------------
+ bool DataNavigatorWindow::HasFirstInstancePage() const
+ {
+ return ( m_aTabCtrl.GetPageId( 0 ) == TID_INSTANCE );
+ }
+
+ //------------------------------------------------------------------------
+ USHORT DataNavigatorWindow::GetNewPageId() const
+ {
+ USHORT i, nMax = 0, nCount = m_aTabCtrl.GetPageCount();
+ for ( i = 0; i < nCount; ++i )
+ {
+ if ( nMax < m_aTabCtrl.GetPageId(i) )
+ nMax = m_aTabCtrl.GetPageId(i);
+ }
+ return ( nMax + 1 );
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::Resize()
+ {
+ Window::Resize();
+
+ Size aOutSz = GetOutputSizePixel();
+ long nWidth = Max( aOutSz.Width(), m_nMinWidth );
+ long nHeight = Max( aOutSz.Height(), m_nMinHeight );
+
+ Size aSz = m_aModelsBox.GetSizePixel();
+ aSz.Width() = nWidth - 3*m_a3Size.Width() - m_aModelBtn.GetSizePixel().Width();
+ m_aModelsBox.SetSizePixel( aSz );
+ Point aPos = m_aModelBtn.GetPosPixel();
+ aPos.X() = m_aModelsBox.GetPosPixel().X() + aSz.Width() + m_a3Size.Width();
+ m_aModelBtn.SetPosPixel( aPos );
+
+ aSz = m_aTabCtrl.GetSizePixel();
+ aSz.Width() = nWidth - 2*m_a3Size.Width();
+ aSz.Height() = nHeight - m_nBorderHeight;
+ m_aTabCtrl.SetSizePixel( aSz );
+ // Instance button positioning
+ aPos = m_aInstanceBtn.GetPosPixel();
+ // right aligned
+ aPos.X() = nWidth - m_aInstanceBtn.GetSizePixel().Width() - m_a3Size.Width();
+ // under the tabcontrol
+ aPos.Y() = m_aTabCtrl.GetPosPixel().Y() + aSz.Height() + m_a3Size.Height();
+ m_aInstanceBtn.SetPosPixel( aPos );
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::SetDocModified()
+ {
+ SfxObjectShell* pCurrentDoc = SfxObjectShell::Current();
+ DBG_ASSERT( pCurrentDoc, "DataNavigatorWindow::SetDocModified(): no objectshell" );
+ if ( !pCurrentDoc->IsModified() && pCurrentDoc->IsEnableSetModified() )
+ pCurrentDoc->SetModified();
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::NotifyChanges( bool _bLoadAll )
+ {
+ if ( !m_bIsNotifyDisabled )
+ {
+ if ( _bLoadAll )
+ {
+ // reset all members
+ RemoveBroadcaster();
+ m_xDataContainer.clear();
+ m_xFrameModel.clear();
+ m_aModelsBox.Clear();
+ m_nLastSelectedPos = LISTBOX_ENTRY_NOTFOUND;
+ // for a reload
+ LoadModels();
+ }
+ else
+ m_aUpdateTimer.Start();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::AddContainerBroadcaster( const XContainer_ref& xContainer )
+ {
+ Reference< XContainerListener > xListener(
+ static_cast< XContainerListener* >( m_xDataListener.get() ), UNO_QUERY );
+ xContainer->addContainerListener( xListener );
+ m_aContainerList.push_back( xContainer );
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::AddEventBroadcaster( const XEventTarget_ref& xTarget )
+ {
+ Reference< XEventListener > xListener(
+ static_cast< XEventListener* >( m_xDataListener.get() ), UNO_QUERY );
+ xTarget->addEventListener( EVENTTYPE_CHARDATA, xListener, true );
+ xTarget->addEventListener( EVENTTYPE_CHARDATA, xListener, false );
+ xTarget->addEventListener( EVENTTYPE_ATTR, xListener, true );
+ xTarget->addEventListener( EVENTTYPE_ATTR, xListener, false );
+ m_aEventTargetList.push_back( xTarget );
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigatorWindow::RemoveBroadcaster()
+ {
+ Reference< XContainerListener > xContainerListener(
+ static_cast< XContainerListener* >( m_xDataListener.get() ), UNO_QUERY );
+ sal_Int32 i, nCount = m_aContainerList.size();
+ for ( i = 0; i < nCount; ++i )
+ m_aContainerList[i]->removeContainerListener( xContainerListener );
+ Reference< XEventListener > xEventListener(
+ static_cast< XEventListener* >( m_xDataListener.get() ), UNO_QUERY );
+ nCount = m_aEventTargetList.size();
+ for ( i = 0; i < nCount; ++i )
+ {
+ m_aEventTargetList[i]->removeEventListener( EVENTTYPE_CHARDATA, xEventListener, true );
+ m_aEventTargetList[i]->removeEventListener( EVENTTYPE_CHARDATA, xEventListener, false );
+ m_aEventTargetList[i]->removeEventListener( EVENTTYPE_ATTR, xEventListener, true );
+ m_aEventTargetList[i]->removeEventListener( EVENTTYPE_ATTR, xEventListener, false );
+ }
+ }
+
+ //========================================================================
+ // class DataNavigator
+ //========================================================================
+ DBG_NAME(DataNavigator)
+ //------------------------------------------------------------------------
+ DataNavigator::DataNavigator( SfxBindings* _pBindings, SfxChildWindow* _pMgr, Window* _pParent ) :
+
+ SfxDockingWindow( _pBindings, _pMgr, _pParent,
+ WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) ),
+ SfxControllerItem( SID_FM_DATANAVIGATOR_CONTROL, *_pBindings ),
+
+ m_aDataWin( this, _pBindings )
+
+ {
+ DBG_CTOR(DataNavigator,NULL);
+
+ SetHelpId( HID_DATA_NAVIGATOR_WIN );
+ SetText( SVX_RES( RID_STR_DATANAVIGATOR ) );
+
+ Size aSize = m_aDataWin.GetOutputSizePixel();
+ Size aLogSize = PixelToLogic( aSize, MAP_APPFONT );
+ SfxDockingWindow::SetFloatingSize( aLogSize );
+
+ m_aDataWin.Show();
+ }
+
+ //------------------------------------------------------------------------
+ DataNavigator::~DataNavigator()
+ {
+ DBG_DTOR(DataNavigator,NULL);
+ }
+
+ //-----------------------------------------------------------------------
+ void DataNavigator::Update( FmFormShell* /*pFormShell*/ )
+ {
+ }
+ //-----------------------------------------------------------------------
+ void DataNavigator::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
+ {
+ if ( !pState || SID_FM_DATANAVIGATOR_CONTROL != nSID )
+ return;
+
+ if ( eState >= SFX_ITEM_AVAILABLE )
+ {
+ FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() );
+ Update( pShell );
+ }
+ else
+ Update( NULL );
+ }
+
+ //-----------------------------------------------------------------------
+ void DataNavigator::GetFocus()
+ {
+ SfxDockingWindow::GetFocus();
+ }
+
+ //-----------------------------------------------------------------------
+ sal_Bool DataNavigator::Close()
+ {
+ Update( NULL );
+ return SfxDockingWindow::Close();
+ }
+
+ //-----------------------------------------------------------------------
+ Size DataNavigator::CalcDockingSize( SfxChildAlignment eAlign )
+ {
+ if ( ( eAlign == SFX_ALIGN_TOP ) || ( eAlign == SFX_ALIGN_BOTTOM ) )
+ return Size();
+
+ return SfxDockingWindow::CalcDockingSize( eAlign );
+ }
+
+ //-----------------------------------------------------------------------
+ SfxChildAlignment DataNavigator::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign )
+ {
+ switch ( eAlign )
+ {
+ case SFX_ALIGN_LEFT:
+ case SFX_ALIGN_RIGHT:
+ case SFX_ALIGN_NOALIGNMENT:
+ return eAlign;
+ default:
+ break;
+ }
+ return eActAlign;
+ }
+
+ //------------------------------------------------------------------------
+ void DataNavigator::Resize()
+ {
+ SfxDockingWindow::Resize();
+
+ Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT );
+ Size aLogExplSize = aLogOutputSize;
+ aLogExplSize.Width() -= 2;
+ aLogExplSize.Height() -= 2;
+
+ Point aExplPos = LogicToPixel( Point(1,1), MAP_APPFONT );
+ Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT );
+
+ m_aDataWin.SetPosSizePixel( aExplPos, aExplSize );
+ }
+
+
+ //========================================================================
+ // class NavigatorFrameManager
+ //========================================================================
+
+ //-----------------------------------------------------------------------
+ SFX_IMPL_DOCKINGWINDOW( DataNavigatorManager, SID_FM_SHOW_DATANAVIGATOR )
+
+ //-----------------------------------------------------------------------
+ DataNavigatorManager::DataNavigatorManager(
+ Window* _pParent, sal_uInt16 _nId, SfxBindings* _pBindings, SfxChildWinInfo* _pInfo ) :
+
+ SfxChildWindow( _pParent, _nId )
+
+ {
+ pWindow = new DataNavigator( _pBindings, this, _pParent );
+ eChildAlignment = SFX_ALIGN_RIGHT;
+ pWindow->SetSizePixel( Size( 250, 400 ) );
+ ( (SfxDockingWindow*)pWindow )->Initialize( _pInfo );
+ }
+
+ //========================================================================
+ // class AddDataItemDialog
+ //========================================================================
+
+ AddDataItemDialog::AddDataItemDialog(
+ Window* pParent, ItemNode* _pNode,
+ const Reference< css::xforms::XFormsUIHelper1 >& _rUIHelper ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_ADD_DATAITEM ) ),
+
+ m_aItemFL ( this, SVX_RES( FL_ITEM ) ),
+ m_aNameFT ( this, SVX_RES( FT_NAME ) ),
+ m_aNameED ( this, SVX_RES( ED_NAME ) ),
+ m_aDefaultFT ( this, SVX_RES( FT_DEFAULT ) ),
+ m_aDefaultED ( this, SVX_RES( ED_DEFAULT ) ),
+ m_aDefaultBtn ( this, SVX_RES( PB_DEFAULT ) ),
+ m_aSettingsFL ( this, SVX_RES( FL_SETTINGS ) ),
+ m_aDataTypeFT ( this, SVX_RES( FT_DATATYPE ) ),
+ m_aDataTypeLB ( this, SVX_RES( LB_DATATYPE ) ),
+ m_aRequiredCB ( this, SVX_RES( CB_REQUIRED ) ),
+ m_aRequiredBtn ( this, SVX_RES( PB_REQUIRED ) ),
+ m_aRelevantCB ( this, SVX_RES( CB_RELEVANT ) ),
+ m_aRelevantBtn ( this, SVX_RES( PB_RELEVANT ) ),
+ m_aConstraintCB ( this, SVX_RES( CB_CONSTRAINT ) ),
+ m_aConstraintBtn( this, SVX_RES( PB_CONSTRAINT ) ),
+ m_aReadonlyCB ( this, SVX_RES( CB_READONLY ) ),
+ m_aReadonlyBtn ( this, SVX_RES( PB_READONLY ) ),
+ m_aCalculateCB ( this, SVX_RES( CB_CALCULATE ) ),
+ m_aCalculateBtn ( this, SVX_RES( PB_CALCULATE ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) ),
+
+ m_xUIHelper ( _rUIHelper ),
+ m_pItemNode ( _pNode ),
+ m_eItemType ( DITNone ),
+ m_sFL_Element ( SVX_RES( STR_FIXEDLINE_ELEMENT ) ),
+ m_sFL_Attribute ( SVX_RES( STR_FIXEDLINE_ATTRIBUTE ) ),
+ m_sFL_Binding ( SVX_RES( STR_FIXEDLINE_BINDING ) ),
+ m_sFT_BindingExp( SVX_RES( STR_FIXEDTEXT_BINDING ) )
+
+ {
+ FreeResource();
+ m_aDataTypeLB.SetDropDownLineCount( 10 );
+
+ InitDialog();
+ InitFromNode();
+ InitDataTypeBox();
+ CheckHdl( NULL );
+ }
+
+ //------------------------------------------------------------------------
+ AddDataItemDialog::~AddDataItemDialog()
+ {
+ if ( m_xTempBinding.is() )
+ {
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ try
+ {
+ Reference < XSet > xBindings = xModel->getBindings();
+ if ( xBindings.is() )
+ xBindings->remove( makeAny( m_xTempBinding ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::Dtor(): exception caught" );
+ }
+ }
+ }
+ if( m_xUIHelper.is() && m_xBinding.is() )
+ {
+ // remove binding, if it does not convey 'useful' information
+ m_xUIHelper->removeBindingIfUseless( m_xBinding );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddDataItemDialog, CheckHdl, CheckBox *, pBox )
+ {
+ // Condition buttons are only enable if their check box is checked
+ m_aReadonlyBtn.Enable( m_aReadonlyCB.IsChecked() );
+ m_aRequiredBtn.Enable( m_aRequiredCB.IsChecked() );
+ m_aRelevantBtn.Enable( m_aRelevantCB.IsChecked() );
+ m_aConstraintBtn.Enable( m_aConstraintCB.IsChecked() );
+ m_aCalculateBtn.Enable( m_aCalculateCB.IsChecked() );
+
+ if ( pBox && m_xTempBinding.is() )
+ {
+ ::rtl::OUString sTemp, sPropName;
+ if ( &m_aRequiredCB == pBox )
+ sPropName = PN_REQUIRED_EXPR;
+ else if ( &m_aRelevantCB == pBox )
+ sPropName = PN_RELEVANT_EXPR;
+ else if ( &m_aConstraintCB == pBox )
+ sPropName = PN_CONSTRAINT_EXPR;
+ else if ( &m_aReadonlyCB == pBox )
+ sPropName = PN_READONLY_EXPR;
+ else if ( &m_aCalculateCB == pBox )
+ sPropName = PN_CALCULATE_EXPR;
+ bool bIsChecked = ( pBox->IsChecked() != FALSE );
+ m_xTempBinding->getPropertyValue( sPropName ) >>= sTemp;
+ if ( bIsChecked && sTemp.getLength() == 0 )
+ sTemp = TRUE_VALUE;
+ else if ( !bIsChecked && sTemp.getLength() > 0 )
+ sTemp = ::rtl::OUString();
+ m_xTempBinding->setPropertyValue( sPropName, makeAny( sTemp ) );
+ }
+
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddDataItemDialog, ConditionHdl, PushButton *, pBtn )
+ {
+ ::rtl::OUString sTemp, sPropName;
+ if ( &m_aDefaultBtn == pBtn )
+ sPropName = PN_BINDING_EXPR;
+ else if ( &m_aRequiredBtn == pBtn )
+ sPropName = PN_REQUIRED_EXPR;
+ else if ( &m_aRelevantBtn == pBtn )
+ sPropName = PN_RELEVANT_EXPR;
+ else if ( &m_aConstraintBtn == pBtn )
+ sPropName = PN_CONSTRAINT_EXPR;
+ else if ( &m_aReadonlyBtn == pBtn )
+ sPropName = PN_READONLY_EXPR;
+ else if ( &m_aCalculateBtn == pBtn )
+ sPropName = PN_CALCULATE_EXPR;
+ AddConditionDialog aDlg( this, sPropName, m_xTempBinding );
+ bool bIsDefBtn = ( &m_aDefaultBtn == pBtn );
+ String sCondition;
+ if ( bIsDefBtn )
+ sCondition = m_aDefaultED.GetText();
+ else
+ {
+ m_xTempBinding->getPropertyValue( sPropName ) >>= sTemp;
+ if ( sTemp.getLength() == 0 )
+ sTemp = TRUE_VALUE;
+ sCondition = sTemp;
+ }
+ aDlg.SetCondition( sCondition );
+
+ if ( aDlg.Execute() == RET_OK )
+ {
+ String sNewCondition = aDlg.GetCondition();
+ if ( bIsDefBtn )
+ m_aDefaultED.SetText( sNewCondition );
+ else
+ {
+
+ m_xTempBinding->setPropertyValue(
+ sPropName, makeAny( ::rtl::OUString( sNewCondition ) ) );
+ }
+ }
+ return 0;
+ }
+
+ void copyPropSet( const Reference< XPropertySet >& xFrom, Reference< XPropertySet >& xTo )
+ {
+ DBG_ASSERT( xFrom.is(), "copyPropSet(): no source" );
+ DBG_ASSERT( xTo.is(), "copyPropSet(): no target" );
+
+ try
+ {
+ // get property names & infos, and iterate over target properties
+ Sequence< Property > aProperties = xTo->getPropertySetInfo()->getProperties();
+ sal_Int32 nProperties = aProperties.getLength();
+ const Property* pProperties = aProperties.getConstArray();
+ Reference< XPropertySetInfo > xFromInfo = xFrom->getPropertySetInfo();
+ for ( sal_Int32 i = 0; i < nProperties; ++i )
+ {
+ const ::rtl::OUString& rName = pProperties[i].Name;
+
+ // if both set have the property, copy the value
+ // (catch and ignore exceptions, if any)
+ if ( xFromInfo->hasPropertyByName( rName ) )
+ {
+ // don't set readonly properties
+ Property aProperty = xFromInfo->getPropertyByName( rName );
+ if ( ( aProperty.Attributes & PropertyAttribute::READONLY ) == 0 )
+ xTo->setPropertyValue(rName, xFrom->getPropertyValue( rName ));
+ }
+ // else: no property? then ignore.
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "copyPropSet(): exception caught" );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddDataItemDialog, OKHdl, OKButton *, EMPTYARG )
+ {
+ bool bIsHandleBinding = ( DITBinding == m_eItemType );
+ bool bIsHandleText = ( DITText == m_eItemType );
+ ::rtl::OUString sNewName( m_aNameED.GetText() );
+
+ if ( ( !bIsHandleBinding && !bIsHandleText && !m_xUIHelper->isValidXMLName( sNewName ) ) ||
+ ( bIsHandleBinding && sNewName.getLength() == 0 ) )
+ {
+ // Error and don't close the dialog
+ ErrorBox aErrBox( this, SVX_RES( RID_ERR_INVALID_XMLNAME ) );
+ String sMessText = aErrBox.GetMessText();
+ sMessText.SearchAndReplace( MSG_VARIABLE, sNewName );
+ aErrBox.SetMessText( sMessText );
+ aErrBox.Execute();
+ return 0;
+ }
+
+ ::rtl::OUString sDataType( m_aDataTypeLB.GetSelectEntry() );
+ m_xTempBinding->setPropertyValue( PN_BINDING_TYPE, makeAny( sDataType ) );
+
+ if ( bIsHandleBinding )
+ {
+ // copy properties from temp binding to original binding
+ copyPropSet( m_xTempBinding, m_pItemNode->m_xPropSet );
+ try
+ {
+ ::rtl::OUString sValue = m_aNameED.GetText();
+ m_pItemNode->m_xPropSet->setPropertyValue( PN_BINDING_ID, makeAny( sValue ) );
+ sValue = m_aDefaultED.GetText();
+ m_pItemNode->m_xPropSet->setPropertyValue( PN_BINDING_EXPR, makeAny( sValue ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataDialog::OKHdl(): exception caught" );
+ }
+ }
+ else
+ {
+ // copy properties from temp binding to original binding
+ copyPropSet( m_xTempBinding, m_xBinding );
+ try
+ {
+ if ( bIsHandleText )
+ m_xUIHelper->setNodeValue( m_pItemNode->m_xNode, m_aDefaultED.GetText() );
+ else
+ {
+ Reference< css::xml::dom::XNode > xNewNode =
+ m_xUIHelper->renameNode( m_pItemNode->m_xNode, m_aNameED.GetText() );
+ m_xUIHelper->setNodeValue( xNewNode, m_aDefaultED.GetText() );
+ m_pItemNode->m_xNode = xNewNode;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataDialog::OKHdl(): exception caught" );
+ }
+ }
+ // then close the dialog
+ EndDialog( RET_OK );
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ void AddDataItemDialog::InitDialog()
+ {
+ // set handler
+ Link aLink = LINK( this, AddDataItemDialog, CheckHdl );
+ m_aRequiredCB.SetClickHdl( aLink );
+ m_aRelevantCB.SetClickHdl( aLink );
+ m_aConstraintCB.SetClickHdl( aLink );
+ m_aReadonlyCB.SetClickHdl( aLink );
+ m_aCalculateCB.SetClickHdl( aLink );
+
+ aLink = LINK( this, AddDataItemDialog, ConditionHdl );
+ m_aDefaultBtn.SetClickHdl( aLink );
+ m_aRequiredBtn.SetClickHdl( aLink );
+ m_aRelevantBtn.SetClickHdl( aLink );
+ m_aConstraintBtn.SetClickHdl( aLink );
+ m_aReadonlyBtn.SetClickHdl( aLink );
+ m_aCalculateBtn.SetClickHdl( aLink );
+
+ m_aOKBtn.SetClickHdl( LINK( this, AddDataItemDialog, OKHdl ) );
+ }
+
+ //------------------------------------------------------------------------
+ void AddDataItemDialog::InitFromNode()
+ {
+ if ( m_pItemNode )
+ {
+ if ( m_pItemNode->m_xNode.is() )
+ {
+ try
+ {
+ // detect type of the node
+ css::xml::dom::NodeType eChildType = m_pItemNode->m_xNode->getNodeType();
+ switch ( eChildType )
+ {
+ case css::xml::dom::NodeType_ATTRIBUTE_NODE:
+ m_eItemType = DITAttribute;
+ break;
+ case css::xml::dom::NodeType_ELEMENT_NODE:
+ m_eItemType = DITElement;
+ break;
+ case css::xml::dom::NodeType_TEXT_NODE:
+ m_eItemType = DITText;
+ break;
+ default:
+ DBG_ERROR( "AddDataItemDialog::InitFronNode: cannot handle this node type!" );
+ break;
+ }
+
+ /** Get binding of the node and clone it
+ Then use this temporary binding in the dialog.
+ When the user click OK the temporary binding will be copied
+ into the original binding.
+ */
+
+ Reference< css::xml::dom::XNode > xNode = m_pItemNode->m_xNode;
+ m_xBinding = m_xUIHelper->getBindingForNode( xNode, sal_True );
+ if ( m_xBinding.is() )
+ {
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ m_xTempBinding = m_xUIHelper->cloneBindingAsGhost( m_xBinding );
+ Reference < XSet > xBindings = xModel->getBindings();
+ if ( xBindings.is() )
+ xBindings->insert( makeAny( m_xTempBinding ) );
+ }
+ }
+
+ if ( m_eItemType != DITText )
+ {
+ ::rtl::OUString sName( m_xUIHelper->getNodeName( m_pItemNode->m_xNode ) );
+ m_aNameED.SetText( sName );
+ }
+ m_aDefaultED.SetText( m_pItemNode->m_xNode->getNodeValue() );
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::InitFromNode(): exception caught" );
+ }
+ }
+ else if ( m_pItemNode->m_xPropSet.is() )
+ {
+ m_eItemType = DITBinding;
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ try
+ {
+ m_xTempBinding = m_xUIHelper->cloneBindingAsGhost( m_pItemNode->m_xPropSet );
+ Reference < XSet > xBindings = xModel->getBindings();
+ if ( xBindings.is() )
+ xBindings->insert( makeAny( m_xTempBinding ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::InitFromNode(): exception caught" );
+ }
+ }
+ rtl::OUString sTemp;
+ try
+ {
+ Reference< XPropertySetInfo > xInfo = m_pItemNode->m_xPropSet->getPropertySetInfo();
+ if ( xInfo->hasPropertyByName( PN_BINDING_ID ) )
+ {
+ m_pItemNode->m_xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
+ m_aNameED.SetText( sTemp );
+ m_pItemNode->m_xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
+ m_aDefaultED.SetText( sTemp );
+ }
+ else if ( xInfo->hasPropertyByName( PN_SUBMISSION_BIND ) )
+ {
+ m_pItemNode->m_xPropSet->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
+ m_aNameED.SetText( sTemp );
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::InitFromNode(): exception caught" );
+ }
+
+ Size a3and1Sz = LogicToPixel( Size( 3, 1 ), MAP_APPFONT );
+ Size aNewSz = m_aDefaultED.GetSizePixel();
+ Point aNewPnt = m_aDefaultED.GetPosPixel();
+ aNewPnt.Y() += a3and1Sz.Height();
+ aNewSz.Width() -= ( m_aDefaultBtn.GetSizePixel().Width() + a3and1Sz.Width() );
+ m_aDefaultED.SetPosSizePixel( aNewPnt, aNewSz );
+ m_aDefaultBtn.Show();
+ }
+
+ if ( m_xTempBinding.is() )
+ {
+ ::rtl::OUString sTemp;
+ try
+ {
+ if ( ( m_xTempBinding->getPropertyValue( PN_REQUIRED_EXPR ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ m_aRequiredCB.Check( TRUE );
+ if ( ( m_xTempBinding->getPropertyValue( PN_RELEVANT_EXPR ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ m_aRelevantCB.Check( TRUE );
+ if ( ( m_xTempBinding->getPropertyValue( PN_CONSTRAINT_EXPR ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ m_aConstraintCB.Check( TRUE );
+ if ( ( m_xTempBinding->getPropertyValue( PN_READONLY_EXPR ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ m_aReadonlyCB.Check( TRUE );
+ if ( ( m_xTempBinding->getPropertyValue( PN_CALCULATE_EXPR ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ m_aCalculateCB.Check( TRUE );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::InitFromNode(): exception caught" );
+ }
+ }
+ }
+
+ if ( DITText == m_eItemType )
+ {
+ long nDelta = m_aButtonsFL.GetPosPixel().Y() - m_aSettingsFL.GetPosPixel().Y();
+ size_t i = 0;
+ Window* pWinsForHide[] =
+ {
+ &m_aSettingsFL, &m_aDataTypeFT, &m_aDataTypeLB, &m_aRequiredCB,
+ &m_aRequiredBtn, &m_aRelevantCB, &m_aRelevantBtn, &m_aConstraintCB,
+ &m_aConstraintBtn, &m_aReadonlyCB, &m_aReadonlyBtn, &m_aCalculateCB,
+ &m_aCalculateBtn
+ };
+ Window** pCurrent = pWinsForHide;
+ for ( ; i < SAL_N_ELEMENTS( pWinsForHide ); ++i, ++pCurrent )
+ (*pCurrent)->Hide();
+
+ Window* pWinsForMove[] =
+ {
+ &m_aButtonsFL, &m_aOKBtn, &m_aEscBtn, &m_aHelpBtn
+ };
+ pCurrent = pWinsForMove;
+ for ( i = 0; i < SAL_N_ELEMENTS( pWinsForMove ); ++i, ++pCurrent )
+ {
+ Point aNewPos = (*pCurrent)->GetPosPixel();
+ aNewPos.Y() -= nDelta;
+ (*pCurrent)->SetPosPixel( aNewPos );
+ }
+ Size aNewWinSz = GetSizePixel();
+ aNewWinSz.Height() -= nDelta;
+ SetSizePixel( aNewWinSz );
+
+ m_aNameFT.Disable();
+ m_aNameED.Disable();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void AddDataItemDialog::InitDataTypeBox()
+ {
+ if ( m_eItemType != DITText )
+ {
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ try
+ {
+ Reference< css::xforms::XDataTypeRepository > xDataTypes =
+ xModel->getDataTypeRepository();
+ if ( xDataTypes.is() )
+ {
+ Sequence< ::rtl::OUString > aNameList = xDataTypes->getElementNames();
+ sal_Int32 i, nCount = aNameList.getLength();
+ ::rtl::OUString* pNames = aNameList.getArray();
+ for ( i = 0; i < nCount; ++i )
+ m_aDataTypeLB.InsertEntry( pNames[i] );
+ }
+
+ if ( m_xTempBinding.is() )
+ {
+ rtl::OUString sTemp;
+ if ( m_xTempBinding->getPropertyValue( PN_BINDING_TYPE ) >>= sTemp )
+ {
+ USHORT nPos = m_aDataTypeLB.GetEntryPos( String( sTemp ) );
+ if ( LISTBOX_ENTRY_NOTFOUND == nPos )
+ nPos = m_aDataTypeLB.InsertEntry( sTemp );
+ m_aDataTypeLB.SelectEntryPos( nPos );
+ }
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::InitDataTypeBox(): exception caught" );
+ }
+ }
+ }
+ }
+
+ void AddDataItemDialog::InitText( DataItemType _eType )
+ {
+ String sText;
+
+ switch ( _eType )
+ {
+ case DITAttribute :
+ {
+ sText = m_sFL_Attribute;
+ break;
+ }
+
+ case DITBinding :
+ {
+ sText = m_sFL_Binding;
+ m_aDefaultFT.SetText( m_sFT_BindingExp );
+ break;
+ }
+
+ default:
+ {
+ sText = m_sFL_Element;
+ }
+ }
+
+ m_aItemFL.SetText( sText );
+ }
+
+ //========================================================================
+ // class AddConditionDialog
+ //========================================================================
+
+ AddConditionDialog::AddConditionDialog(
+ Window* pParent, const ::rtl::OUString& _rPropertyName,
+ const Reference< XPropertySet >& _rPropSet ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_ADD_CONDITION ) ),
+
+ m_aConditionFT ( this, SVX_RES( FT_CONDITION ) ),
+ m_aConditionED ( this, SVX_RES( ED_CONDITION ) ),
+ m_aResultFT ( this, SVX_RES( FT_RESULT ) ),
+ m_aResultWin ( this, SVX_RES( FT_RESULT_PREVIEW ) ),
+ m_aEditNamespacesBtn( this, SVX_RES( PB_EDIT_NAMESPACES ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) ),
+
+ m_sPropertyName ( _rPropertyName ),
+ m_xBinding ( _rPropSet )
+
+ {
+ FreeResource();
+
+ DBG_ASSERT( m_xBinding.is(), "AddConditionDialog::Ctor(): no Binding" );
+
+ m_aResultWin.SetBackground( m_aConditionED.GetBackground() );
+ m_aConditionED.SetModifyHdl( LINK( this, AddConditionDialog, ModifyHdl ) );
+ m_aEditNamespacesBtn.SetClickHdl( LINK( this, AddConditionDialog, EditHdl ) );
+ m_aOKBtn.SetClickHdl( LINK( this, AddConditionDialog, OKHdl ) );
+ m_aResultTimer.SetTimeout( 500 );
+ m_aResultTimer.SetTimeoutHdl( LINK( this, AddConditionDialog, ResultHdl ) );
+
+ if ( m_sPropertyName.getLength() > 0 )
+ {
+ try
+ {
+ rtl::OUString sTemp;
+ if ( ( m_xBinding->getPropertyValue( m_sPropertyName ) >>= sTemp )
+ && sTemp.getLength() > 0 )
+ {
+ m_aConditionED.SetText( sTemp );
+ }
+ else
+ {
+//! m_xBinding->setPropertyValue( m_sPropertyName, makeAny( TRUE_VALUE ) );
+ m_aConditionED.SetText( TRUE_VALUE );
+ }
+
+ Reference< css::xforms::XModel > xModel;
+ if ( ( m_xBinding->getPropertyValue( PN_BINDING_MODEL ) >>= xModel ) && xModel.is() )
+ m_xUIHelper = Reference< css::xforms::XFormsUIHelper1 >( xModel, UNO_QUERY );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddConditionDialog::Ctor(): exception caught" );
+ }
+ }
+
+ DBG_ASSERT( m_xUIHelper.is(), "AddConditionDialog::Ctor(): no UIHelper" );
+ ResultHdl( &m_aResultTimer );
+ }
+
+ //------------------------------------------------------------------------
+ AddConditionDialog::~AddConditionDialog()
+ {
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddConditionDialog, EditHdl, PushButton *, EMPTYARG )
+ {
+ Reference< XNameContainer > xNameContnr;
+ try
+ {
+ m_xBinding->getPropertyValue( PN_BINDING_NAMESPACES ) >>= xNameContnr;
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::EditHdl(): exception caught" );
+ }
+ NamespaceItemDialog aDlg( this, xNameContnr );
+ aDlg.Execute();
+ try
+ {
+ m_xBinding->setPropertyValue( PN_BINDING_NAMESPACES, makeAny( xNameContnr ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddDataItemDialog::EditHdl(): exception caught" );
+ }
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddConditionDialog, OKHdl, OKButton *, EMPTYARG )
+ {
+/*!!!
+ try
+ {
+ if ( m_xBinding.is() )
+ m_xBinding->setPropertyValue( m_sPropertyName, makeAny( ::rtl::OUString( m_aConditionED.GetText() ) ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_ERRORFILE( "AddConditionDialog, OKHdl: caught an exception!" );
+ }
+*/
+ EndDialog( RET_OK );
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddConditionDialog, ModifyHdl, MultiLineEdit *, EMPTYARG )
+ {
+ m_aResultTimer.Start();
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddConditionDialog, ResultHdl, Timer *, EMPTYARG )
+ {
+ String sCondition = m_aConditionED.GetText().EraseLeadingChars().EraseTrailingChars();
+ String sResult;
+ if ( sCondition.Len() > 0 )
+ {
+ try
+ {
+ sResult = m_xUIHelper->getResultForExpression( m_xBinding, ( m_sPropertyName == PN_BINDING_EXPR ), sCondition );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddConditionDialog::ResultHdl(): exception caught" );
+ }
+ }
+ m_aResultWin.SetText( sResult );
+ return 0;
+ }
+
+ //========================================================================
+ // class NamespaceItemDialog
+ //========================================================================
+
+ NamespaceItemDialog::NamespaceItemDialog(
+ AddConditionDialog* _pCondDlg, Reference< XNameContainer >& _rContainer ) :
+
+ ModalDialog( _pCondDlg, SVX_RES( RID_SVXDLG_NAMESPACE_ITEM ) ),
+
+ m_aNamespacesFT ( this, SVX_RES( FT_NAMESPACES ) ),
+ m_aNamespacesList ( this, SVX_RES( LB_NAMESPACES ) ),
+ m_aAddNamespaceBtn ( this, SVX_RES( PB_ADD_NAMESPACE ) ),
+ m_aEditNamespaceBtn ( this, SVX_RES( PB_EDIT_NAMESPACE ) ),
+ m_aDeleteNamespaceBtn ( this, SVX_RES( PB_DELETE_NAMESPACE ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) ),
+
+ m_pConditionDlg ( _pCondDlg ),
+ m_rNamespaces ( _rContainer )
+
+ {
+ static long aStaticTabs[]= { 3, 0, 35, 200 };
+ m_aNamespacesList.SvxSimpleTable::SetTabs( aStaticTabs );
+ String sHeader = String( SVX_RES( STR_HEADER_PREFIX ) );
+ sHeader += '\t';
+ sHeader += String( SVX_RES( STR_HEADER_URL ) );
+ m_aNamespacesList.InsertHeaderEntry(
+ sHeader, HEADERBAR_APPEND, HIB_LEFT /*| HIB_FIXEDPOS | HIB_FIXED*/ );
+
+ FreeResource();
+
+ m_aNamespacesList.SetSelectHdl( LINK( this, NamespaceItemDialog, SelectHdl ) );
+ Link aLink = LINK( this, NamespaceItemDialog, ClickHdl );
+ m_aAddNamespaceBtn.SetClickHdl( aLink );
+ m_aEditNamespaceBtn.SetClickHdl( aLink );
+ m_aDeleteNamespaceBtn.SetClickHdl( aLink );
+ m_aOKBtn.SetClickHdl( LINK( this, NamespaceItemDialog, OKHdl ) );
+
+ LoadNamespaces();
+ SelectHdl( &m_aNamespacesList );
+ }
+
+ //------------------------------------------------------------------------
+ NamespaceItemDialog::~NamespaceItemDialog()
+ {
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NamespaceItemDialog, SelectHdl, SvxSimpleTable *, EMPTYARG )
+ {
+ BOOL bEnable = ( m_aNamespacesList.FirstSelected() != NULL );
+ m_aEditNamespaceBtn.Enable( bEnable );
+ m_aDeleteNamespaceBtn.Enable( bEnable );
+
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NamespaceItemDialog, ClickHdl, PushButton *, pBtn )
+ {
+ if ( &m_aAddNamespaceBtn == pBtn )
+ {
+ ManageNamespaceDialog aDlg( this, m_pConditionDlg, false );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ String sEntry = aDlg.GetPrefix();
+ sEntry += '\t';
+ sEntry += aDlg.GetURL();
+ m_aNamespacesList.InsertEntry( sEntry );
+ }
+ }
+ else if ( &m_aEditNamespaceBtn == pBtn )
+ {
+ ManageNamespaceDialog aDlg( this, m_pConditionDlg, true );
+ SvLBoxEntry* pEntry = m_aNamespacesList.FirstSelected();
+ DBG_ASSERT( pEntry, "NamespaceItemDialog::ClickHdl(): no entry" );
+ String sPrefix( m_aNamespacesList.GetEntryText( pEntry, 0 ) );
+ aDlg.SetNamespace(
+ sPrefix,
+ m_aNamespacesList.GetEntryText( pEntry, 1 ) );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ // if a prefix was changed, mark the old prefix as 'removed'
+ if( sPrefix != aDlg.GetPrefix() )
+ m_aRemovedList.push_back( sPrefix );
+
+ m_aNamespacesList.SetEntryText( aDlg.GetPrefix(), pEntry, 0 );
+ m_aNamespacesList.SetEntryText( aDlg.GetURL(), pEntry, 1 );
+ }
+ }
+ else if ( &m_aDeleteNamespaceBtn == pBtn )
+ {
+ SvLBoxEntry* pEntry = m_aNamespacesList.FirstSelected();
+ DBG_ASSERT( pEntry, "NamespaceItemDialog::ClickHdl(): no entry" );
+ ::rtl::OUString sPrefix( m_aNamespacesList.GetEntryText( pEntry, 0 ) );
+ m_aRemovedList.push_back( sPrefix );
+ m_aNamespacesList.GetModel()->Remove( pEntry );
+ }
+ else
+ {
+ DBG_ERRORFILE( "NamespaceItemDialog::ClickHdl(): invalid button" );
+ }
+
+ SelectHdl( &m_aNamespacesList );
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NamespaceItemDialog, OKHdl, OKButton *, EMPTYARG )
+ {
+ try
+ {
+ // update namespace container
+ sal_Int32 i, nRemovedCount = m_aRemovedList.size();
+ for( i = 0; i < nRemovedCount; ++i )
+ m_rNamespaces->removeByName( m_aRemovedList[i] );
+
+ sal_Int32 nEntryCount = m_aNamespacesList.GetEntryCount();
+ for( i = 0; i < nEntryCount; ++i )
+ {
+ SvLBoxEntry* pEntry = m_aNamespacesList.GetEntry(i);
+ ::rtl::OUString sPrefix( m_aNamespacesList.GetEntryText( pEntry, 0 ) );
+ ::rtl::OUString sURL( m_aNamespacesList.GetEntryText( pEntry, 1 ) );
+
+ if ( m_rNamespaces->hasByName( sPrefix ) )
+ m_rNamespaces->replaceByName( sPrefix, makeAny( sURL ) );
+ else
+ m_rNamespaces->insertByName( sPrefix, makeAny( sURL ) );
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "NamespaceItemDialog::OKHdl(): exception caught" );
+ }
+ // and close the dialog
+ EndDialog( RET_OK );
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ void NamespaceItemDialog::LoadNamespaces()
+ {
+ try
+ {
+ Sequence< ::rtl::OUString > aAllNames = m_rNamespaces->getElementNames();
+ const ::rtl::OUString* pAllNames = aAllNames.getConstArray();
+ const ::rtl::OUString* pAllNamesEnd = pAllNames + aAllNames.getLength();
+ for ( ; pAllNames != pAllNamesEnd; ++pAllNames )
+ {
+ ::rtl::OUString sURL;
+ ::rtl::OUString sPrefix = *pAllNames;
+ if ( m_rNamespaces->hasByName( sPrefix ) )
+ {
+ Any aAny = m_rNamespaces->getByName( sPrefix );
+ if ( aAny >>= sURL )
+ {
+ String sEntry( sPrefix );
+ sEntry += '\t';
+ sEntry += String( sURL );
+
+ m_aNamespacesList.InsertEntry( sEntry );
+ }
+ }
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "NamespaceItemDialog::LoadNamespaces(): exception caught" );
+ }
+ }
+
+ //========================================================================
+ // class ManageNamespaceDialog
+ //========================================================================
+
+ ManageNamespaceDialog::ManageNamespaceDialog(
+ Window* pParent, AddConditionDialog* _pCondDlg, bool _bIsEdit ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_MANAGE_NAMESPACE ) ),
+
+ m_aPrefixFT ( this, SVX_RES( FT_PREFIX ) ),
+ m_aPrefixED ( this, SVX_RES( ED_PREFIX ) ),
+ m_aUrlFT ( this, SVX_RES( FT_URL ) ),
+ m_aUrlED ( this, SVX_RES( ED_URL ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) ),
+
+ m_pConditionDlg ( _pCondDlg )
+
+ {
+ if ( _bIsEdit )
+ SetText( String( SVX_RES( STR_EDIT_TEXT ) ) );
+
+ FreeResource();
+
+ m_aOKBtn.SetClickHdl( LINK( this, ManageNamespaceDialog, OKHdl ) );
+ }
+
+ //------------------------------------------------------------------------
+ ManageNamespaceDialog::~ManageNamespaceDialog()
+ {
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( ManageNamespaceDialog, OKHdl, OKButton *, EMPTYARG )
+ {
+ String sPrefix = m_aPrefixED.GetText();
+
+ try
+ {
+ if ( !m_pConditionDlg->GetUIHelper()->isValidPrefixName( sPrefix ) )
+ {
+ ErrorBox aErrBox( this, SVX_RES( RID_ERR_INVALID_XMLPREFIX ) );
+ String sMessText = aErrBox.GetMessText();
+ sMessText.SearchAndReplace( MSG_VARIABLE, sPrefix );
+ aErrBox.SetMessText( sMessText );
+ aErrBox.Execute();
+ return 0;
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "ManageNamespacesDialog::OKHdl(): exception caught" );
+ }
+
+ // no error so close the dialog
+ EndDialog( RET_OK );
+ return 0;
+ }
+
+ //========================================================================
+ // class AddSubmissionDialog
+ //========================================================================
+
+ AddSubmissionDialog::AddSubmissionDialog(
+ Window* pParent, ItemNode* _pNode,
+ const Reference< css::xforms::XFormsUIHelper1 >& _rUIHelper ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_ADD_SUBMISSION ) ),
+
+ m_aSubmissionFL ( this, SVX_RES( FL_SUBMISSION ) ),
+ m_aNameFT ( this, SVX_RES( FT_SUBMIT_NAME ) ),
+ m_aNameED ( this, SVX_RES( ED_SUBMIT_NAME ) ),
+ m_aActionFT ( this, SVX_RES( FT_SUBMIT_ACTION ) ),
+ m_aActionED ( this, SVX_RES( ED_SUBMIT_ACTION ) ),
+ m_aMethodFT ( this, SVX_RES( FT_SUBMIT_METHOD ) ),
+ m_aMethodLB ( this, SVX_RES( LB_SUBMIT_METHOD ) ),
+ m_aRefFT ( this, SVX_RES( FT_SUBMIT_REF ) ),
+ m_aRefED ( this, SVX_RES( ED_SUBMIT_REF ) ),
+ m_aRefBtn ( this, SVX_RES( PB_SUBMIT_REF ) ),
+ m_aBindFT ( this, SVX_RES( FT_SUBMIT_BIND ) ),
+ m_aBindLB ( this, SVX_RES( LB_SUBMIT_BIND ) ),
+ m_aReplaceFT ( this, SVX_RES( FT_SUBMIT_REPLACE ) ),
+ m_aReplaceLB ( this, SVX_RES( LB_SUBMIT_REPLACE ) ),
+
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) ),
+
+ m_pItemNode ( _pNode ),
+ m_xUIHelper ( _rUIHelper )
+
+ {
+ FillAllBoxes(); // we need local resources here, so call before FreeResource!!!
+
+ FreeResource();
+
+ m_aRefBtn.SetClickHdl( LINK( this, AddSubmissionDialog, RefHdl ) );
+ m_aOKBtn.SetClickHdl( LINK( this, AddSubmissionDialog, OKHdl ) );
+ }
+
+ //------------------------------------------------------------------------
+ AddSubmissionDialog::~AddSubmissionDialog()
+ {
+ // #i38991# if we have added a binding, we need to remove it as well.
+ if( m_xCreatedBinding.is() && m_xUIHelper.is() )
+ m_xUIHelper->removeBindingIfUseless( m_xCreatedBinding );
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddSubmissionDialog, RefHdl, PushButton *, EMPTYARG )
+ {
+ AddConditionDialog aDlg( this, PN_BINDING_EXPR, m_xTempBinding );
+ aDlg.SetCondition( m_aRefED.GetText() );
+ if ( aDlg.Execute() == RET_OK )
+ m_aRefED.SetText( aDlg.GetCondition() );
+
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddSubmissionDialog, OKHdl, OKButton *, EMPTYARG )
+ {
+ rtl::OUString sName(m_aNameED.GetText());
+ if(!sName.getLength()) {
+
+ ErrorBox aErrorBox(this,SVX_RES(RID_ERR_EMPTY_SUBMISSIONNAME));
+ aErrorBox.SetText( Application::GetDisplayName() );
+ aErrorBox.Execute();
+ return 0;
+ }
+
+ if ( !m_xSubmission.is() )
+ {
+ DBG_ASSERT( !m_xNewSubmission.is(),
+ "AddSubmissionDialog::OKHdl(): new submission already exists" );
+
+ // add a new submission
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ try
+ {
+ m_xNewSubmission = xModel->createSubmission();
+ m_xSubmission = Reference< XPropertySet >( m_xNewSubmission, UNO_QUERY );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddSubmissionDialog::OKHdl(): exception caught" );
+ }
+ }
+ }
+
+ if ( m_xSubmission.is() )
+ {
+ rtl::OUString sTemp = m_aNameED.GetText();
+ try
+ {
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_ID, makeAny( sTemp ) );
+ sTemp = m_aActionED.GetText();
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_ACTION, makeAny( sTemp ) );
+ sTemp = lcl_MethodString::get().toAPI( m_aMethodLB.GetSelectEntry() );
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_METHOD, makeAny( sTemp ) );
+ sTemp = m_aRefED.GetText();
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_REF, makeAny( sTemp ) );
+ String sEntry = m_aBindLB.GetSelectEntry();
+ sEntry.Erase( sEntry.Search( ':' ) );
+ sTemp = sEntry;
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_BIND, makeAny( sTemp ) );
+ sTemp = lcl_ReplaceString::get().toAPI( m_aReplaceLB.GetSelectEntry() );
+ m_xSubmission->setPropertyValue( PN_SUBMISSION_REPLACE, makeAny( sTemp ) );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddSubmissionDialog::OKHdl(): exception caught" );
+ }
+ }
+
+ EndDialog( RET_OK );
+ return 0;
+ }
+
+ //------------------------------------------------------------------------
+ void AddSubmissionDialog::FillAllBoxes()
+ {
+ // method box
+ m_aMethodLB.InsertEntry( String( SVX_RES( STR_METHOD_POST ) ) );
+ m_aMethodLB.InsertEntry( String( SVX_RES( STR_METHOD_PUT ) ) );
+ m_aMethodLB.InsertEntry( String( SVX_RES( STR_METHOD_GET ) ) );
+ m_aMethodLB.SelectEntryPos(0);
+
+ // binding box
+ Reference< css::xforms::XModel > xModel( m_xUIHelper, UNO_QUERY );
+ if ( xModel.is() )
+ {
+ try
+ {
+ Reference< XEnumerationAccess > xNumAccess( xModel->getBindings(), UNO_QUERY );
+ if ( xNumAccess.is() )
+ {
+ Reference < XEnumeration > xNum = xNumAccess->createEnumeration();
+ if ( xNum.is() && xNum->hasMoreElements() )
+ {
+ String sDelim( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
+ while ( xNum->hasMoreElements() )
+ {
+ Reference< XPropertySet > xPropSet;
+ Any aAny = xNum->nextElement();
+ if ( aAny >>= xPropSet )
+ {
+ String sEntry;
+ rtl::OUString sTemp;
+ xPropSet->getPropertyValue( PN_BINDING_ID ) >>= sTemp;
+ sEntry += String( sTemp );
+ sEntry += sDelim;
+ xPropSet->getPropertyValue( PN_BINDING_EXPR ) >>= sTemp;
+ sEntry += String( sTemp );
+ m_aBindLB.InsertEntry( sEntry );
+
+ if ( !m_xTempBinding.is() )
+ m_xTempBinding = xPropSet;
+ }
+ }
+ }
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddSubmissionDialog::FillAllBoxes(): exception caught" );
+ }
+ }
+
+ // #i36342# we need a temporary binding; create one if no existing binding
+ // is found
+ if( !m_xTempBinding.is() )
+ {
+ m_xCreatedBinding = m_xUIHelper->getBindingForNode(
+ Reference<css::xml::dom::XNode>(
+ xModel->getDefaultInstance()->getDocumentElement(),
+ UNO_QUERY_THROW ),
+ sal_True );
+ m_xTempBinding = m_xCreatedBinding;
+ }
+
+ // replace box
+ m_aReplaceLB.InsertEntry( String( SVX_RES( STR_REPLACE_NONE ) ) );
+ m_aReplaceLB.InsertEntry( String( SVX_RES( STR_REPLACE_INST ) ) );
+ m_aReplaceLB.InsertEntry( String( SVX_RES( STR_REPLACE_DOC ) ) );
+
+
+ // init the controls with the values of the submission
+ if ( m_pItemNode && m_pItemNode->m_xPropSet.is() )
+ {
+ m_xSubmission = m_pItemNode->m_xPropSet;
+ rtl::OUString sTemp;
+ try
+ {
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_ID ) >>= sTemp;
+ m_aNameED.SetText( sTemp );
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_ACTION ) >>= sTemp;
+ m_aActionED.SetText( sTemp );
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_REF ) >>= sTemp;
+ m_aRefED.SetText( sTemp );
+
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_METHOD ) >>= sTemp;
+ sTemp = lcl_MethodString::get().toUI( sTemp );
+ USHORT nPos = m_aMethodLB.GetEntryPos( String( sTemp ) );
+ if ( LISTBOX_ENTRY_NOTFOUND == nPos )
+ nPos = m_aMethodLB.InsertEntry( sTemp );
+ m_aMethodLB.SelectEntryPos( nPos );
+
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_BIND ) >>= sTemp;
+ nPos = m_aBindLB.GetEntryPos( String( sTemp ) );
+ if ( LISTBOX_ENTRY_NOTFOUND == nPos )
+ nPos = m_aBindLB.InsertEntry( sTemp );
+ m_aBindLB.SelectEntryPos( nPos );
+
+ m_xSubmission->getPropertyValue( PN_SUBMISSION_REPLACE ) >>= sTemp;
+ sTemp = lcl_ReplaceString::get().toUI( sTemp );
+ if ( sTemp.getLength() == 0 )
+ sTemp = m_aReplaceLB.GetEntry(0); // first entry == "none"
+ nPos = m_aReplaceLB.GetEntryPos( String( sTemp ) );
+ if ( LISTBOX_ENTRY_NOTFOUND == nPos )
+ nPos = m_aReplaceLB.InsertEntry( sTemp );
+ m_aReplaceLB.SelectEntryPos( nPos );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "AddSubmissionDialog::FillAllBoxes(): exception caught" );
+ }
+ }
+
+ m_aRefBtn.Enable( m_xTempBinding.is() );
+ }
+
+ //========================================================================
+ // class AddModelDialog
+ //========================================================================
+
+ AddModelDialog::AddModelDialog( Window* pParent, bool _bEdit ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_ADD_MODEL ) ),
+
+ m_aModelFL ( this, SVX_RES( FL_MODEL ) ),
+ m_aNameFT ( this, SVX_RES( FT_MODEL_NAME ) ),
+ m_aNameED ( this, SVX_RES( ED_MODEL_NAME ) ),
+ m_aModifyCB ( this, SVX_RES( CB_MODIFIES_DOCUMENT ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) )
+
+ {
+ if ( _bEdit )
+ SetText( String( SVX_RES( STR_EDIT_TEXT ) ) );
+
+ FreeResource();
+ }
+
+ AddModelDialog::~AddModelDialog()
+ {
+ }
+
+ //========================================================================
+ // class AddInstanceDialog
+ //========================================================================
+
+ AddInstanceDialog::AddInstanceDialog( Window* pParent, bool _bEdit ) :
+
+ ModalDialog( pParent, SVX_RES( RID_SVXDLG_ADD_INSTANCE ) ),
+
+ m_aInstanceFL ( this, SVX_RES( FL_INSTANCE ) ),
+ m_aNameFT ( this, SVX_RES( FT_INST_NAME ) ),
+ m_aNameED ( this, SVX_RES( ED_INST_NAME ) ),
+ m_aURLFT ( this, SVX_RES( FT_INST_URL ) ),
+ m_aURLED ( this, SVX_RES( ED_INST_URL ) ),
+ m_aFilePickerBtn ( this, SVX_RES( PB_FILEPICKER ) ),
+ m_aLinkInstanceCB ( this, SVX_RES( CB_INST_LINKINST ) ),
+ m_aButtonsFL ( this, SVX_RES( FL_DATANAV_BTN ) ),
+ m_aOKBtn ( this, SVX_RES( BTN_DATANAV_OK ) ),
+ m_aEscBtn ( this, SVX_RES( BTN_DATANAV_ESC ) ),
+ m_aHelpBtn ( this, SVX_RES( BTN_DATANAV_HELP ) )
+
+ {
+ if ( _bEdit )
+ SetText( String( SVX_RES( STR_EDIT_TEXT ) ) );
+
+ FreeResource();
+
+ m_aURLED.DisableHistory();
+ m_aFilePickerBtn.SetClickHdl( LINK( this, AddInstanceDialog, FilePickerHdl ) );
+
+ // load the filter name from fps_office resource
+ m_sAllFilterName = String( ResId( STR_FILTERNAME_ALL, *CREATEVERSIONRESMGR(fps_office) ) );
+ }
+
+ AddInstanceDialog::~AddInstanceDialog()
+ {
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( AddInstanceDialog, FilePickerHdl, PushButton *, EMPTYARG )
+ {
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, 0 );
+ INetURLObject aFile( SvtPathOptions().GetWorkPath() );
+
+ aDlg.AddFilter( m_sAllFilterName, DEFINE_CONST_UNICODE(FILEDIALOG_FILTER_ALL) );
+ String sFilterName( DEFINE_CONST_UNICODE("XML") );
+ aDlg.AddFilter( sFilterName, DEFINE_CONST_UNICODE("*.xml") );
+ aDlg.SetCurrentFilter( sFilterName );
+ aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) );
+
+ if( aDlg.Execute() == ERRCODE_NONE )
+ m_aURLED.SetText( aDlg.GetPath() );
+
+ return 0;
+ }
+
+ //========================================================================
+ // class LinkedInstanceWarningBox
+ //========================================================================
+
+ LinkedInstanceWarningBox::LinkedInstanceWarningBox( Window* pParent ) :
+
+ MessBox( pParent, SVX_RES( RID_QRY_LINK_WARNING ) )
+
+ {
+ SetText( Application::GetDisplayName() );
+ SetImage( QueryBox::GetStandardImage() );
+ AddButton( SVX_RESSTR( RID_STR_DATANAV_LINKWARN_BUTTON ), BUTTONID_OK, BUTTONDIALOG_DEFBUTTON );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, BUTTONDIALOG_CANCELBUTTON );
+ }
+
+//............................................................................
+} // namespace svxform
+//............................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/datanavi.src b/svx/source/form/datanavi.src
new file mode 100644
index 000000000000..f6265b6b0596
--- /dev/null
+++ b/svx/source/form/datanavi.src
@@ -0,0 +1,1148 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "datanavi.hrc"
+#include "globlmn.hrc"
+#include "fmresids.hrc"
+#include "fmhelp.hrc"
+
+#define MASKCOLOR MaskColor = Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; };
+
+TabPage RID_SVX_XFORMS_TABPAGES
+{
+ Hide = TRUE ;
+ DialogControl = TRUE;
+ Size = MAP_APPFONT ( 63 , 100 ) ;
+ ToolBox TB_ITEMS
+ {
+ HelpId = HID_XFORMS_TOOLBOX ;
+ SVLook = TRUE ;
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ ItemList =
+ {
+ ToolBoxItem
+ {
+ Identifier = TBI_ITEM_ADD ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD ;
+ Text [ en-US ] = "Add Item" ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TBI_ITEM_ADD_ELEMENT ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD_ELEMENT ;
+ Text [ en-US ] = "Add Element" ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TBI_ITEM_ADD_ATTRIBUTE ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD_ATTRIBUTE ;
+ Text [ en-US ] = "Add Attribute" ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TBI_ITEM_EDIT ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_EDIT ;
+ Text [ en-US ] = "Edit" ;
+ };
+ ToolBoxItem
+ {
+ Type = TOOLBOXITEM_SEPARATOR ;
+ };
+ ToolBoxItem
+ {
+ Identifier = TBI_ITEM_REMOVE ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_REMOVE ;
+ Text [ en-US ] = "Delete" ;
+ };
+ };
+ };
+ Control LB_ITEMS
+ {
+ HelpId = HID_XFORMS_ITEMS_LIST ;
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 63 , 100 ) ;
+ Border = TRUE ;
+ TabStop = TRUE;
+ };
+#define IMG_LST \
+IdList = \
+{ \
+ IID_ITEM_ADD ; \
+ IID_ITEM_ADD_ELEMENT ; \
+ IID_ITEM_ADD_ATTRIBUTE ; \
+ IID_ITEM_EDIT ; \
+ IID_ITEM_REMOVE ; \
+}; \
+IdCount = { 5 ; } ;
+
+ ImageList IL_TBX_BMPS
+ {
+ Prefix = "tb";
+ MASKCOLOR
+ IMG_LST
+ };
+#undef IMG_LST
+};
+
+Window RID_SVXWIN_DATANAVIGATOR
+{
+ OutputSize = TRUE ;
+ Hide = TRUE ;
+ SVLook = TRUE ;
+ DialogControl = TRUE ;
+ HelpId = HID_DATA_NAVIGATOR_WIN ;
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 300 , 400 ) ;
+ ListBox LB_MODELS
+ {
+ HelpId = HID_XFORMS_MODELS_LIST ;
+ Pos = MAP_APPFONT ( 3 , 4 ) ;
+ Size = MAP_APPFONT ( 63 , 45 ) ;
+ DropDown = TRUE ;
+ DDExtraWidth = TRUE ;
+ };
+ MenuButton MB_MODELS
+ {
+ HelpId = HID_XFORMS_MODELS_MENUBTN ;
+ Pos = MAP_APPFONT ( 69 , 3 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ Text [ en-US ] = "~Models";
+ ButtonMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = MID_MODELS_ADD ;
+ HelpId = HID_MN_XFORMS_MODELS_ADD ;
+ Text [ en-US ] = "~Add..." ;
+ };
+ MenuItem
+ {
+ Identifier = MID_MODELS_EDIT ;
+ HelpId = HID_MN_XFORMS_MODELS_EDIT ;
+ Text [ en-US ] = "~Edit..." ;
+ };
+ MenuItem
+ {
+ Identifier = MID_MODELS_REMOVE ;
+ HelpId = HID_MN_XFORMS_MODELS_REMOVE ;
+ Text [ en-US ] = "~Remove" ;
+ };
+ };
+ };
+ };
+ TabControl TC_ITEMS
+ {
+ HelpId = HID_XFORMS_TAB_CONTROL ;
+ Pos = MAP_APPFONT ( 3, 20 ) ;
+ TabStop = TRUE;
+ PageList =
+ {
+ PageItem
+ {
+ Identifier = TID_INSTANCE ;
+ Text [ en-US ] = "Instance";
+ };
+ PageItem
+ {
+ Identifier = TID_SUBMISSION ;
+ Text [ en-US ] = "Submissions";
+ };
+ PageItem
+ {
+ Identifier = TID_BINDINGS ;
+ Text [ en-US ] = "Bindings";
+ };
+ };
+ };
+ MenuButton MB_INSTANCES
+ {
+ HelpId = HID_XFORMS_INSTANCES_MENUBTN ;
+ Pos = MAP_APPFONT ( 69 , 133 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ Text [ en-US ] = "~Instances";
+ ButtonMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = MID_INSTANCES_ADD ;
+ HelpId = HID_MN_XFORMS_INSTANCES_ADD ;
+ Text [ en-US ] = "~Add..." ;
+ };
+ MenuItem
+ {
+ Identifier = MID_INSTANCES_EDIT ;
+ HelpId = HID_MN_XFORMS_INSTANCES_EDIT ;
+ Text [ en-US ] = "~Edit..." ;
+ };
+ MenuItem
+ {
+ Identifier = MID_INSTANCES_REMOVE ;
+ HelpId = HID_MN_XFORMS_INSTANCES_REMOVE ;
+ Text [ en-US ] = "~Remove" ;
+ };
+ MenuItem
+ {
+ Separator = TRUE;
+ };
+ MenuItem
+ {
+ Identifier = MID_SHOW_DETAILS ;
+ HelpId = HID_MN_XFORMS_SHOW_DETAILS ;
+ Text [ en-US ] = "~Show Details" ;
+ };
+ };
+ };
+ };
+
+#define IMG_LST2 \
+IdList = \
+{ \
+ IID_GROUP_CLOSED ; \
+ IID_GROUP_OPEN ; \
+ IID_ELEMENT ; \
+ IID_ATTRIBUTE ; \
+ IID_TEXT ; \
+ IID_OTHER ; \
+}; \
+IdCount = { 6 ; } ;
+
+ ImageList IL_ITEM_BMPS
+ {
+ Prefix = "da";
+ MASKCOLOR
+ IMG_LST2
+ };
+};
+
+QueryBox RID_QRY_REMOVE_MODEL
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Deleting the model '$MODELNAME' affects all controls currently bound to this model.\nDo you really want to delete this model?" ;
+};
+
+QueryBox RID_QRY_REMOVE_INSTANCE
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Deleting the instance '$INSTANCENAME' affects all controls currently bound to this instance.\nDo you really want to delete this instance?" ;
+};
+
+QueryBox RID_QRY_REMOVE_ELEMENT
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Deleting the element '$ELEMENTNAME' affects all controls currently bound to this element.\nDo you really want to delete this element?" ;
+};
+
+QueryBox RID_QRY_REMOVE_ATTRIBUTE
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Do you really want to delete the attribute '$ATTRIBUTENAME'?" ;
+};
+
+QueryBox RID_QRY_REMOVE_SUBMISSION
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Deleting the submission '$SUBMISSIONNAME' affects all controls currently bound to this submission.\n\nDo you really want to delete this submission?" ;
+};
+
+QueryBox RID_QRY_REMOVE_BINDING
+{
+ Buttons = WB_YES_NO ;
+ DefButton = WB_DEF_NO ;
+ Message [ en-US ] = "Deleting the binding '$BINDINGNAME' affects all controls currently bound to this binding.\n\nDo you really want to delete this binding?" ;
+};
+
+MessBox RID_QRY_LINK_WARNING
+{
+ Buttons = 0 ;
+ Message [ en-US ] = "This instance is linked with the form.\n\nThe changes you make to this instance will be lost when the form is reloaded.\n\nHow do you want to proceed?" ;
+};
+
+ErrorBox RID_ERR_INVALID_XMLNAME
+{
+ Buttons = WB_OK ;
+ Message [ en-US ] = "The name '%1' is not valid in XML. Please enter a different name." ;
+};
+
+ErrorBox RID_ERR_INVALID_XMLPREFIX
+{
+ Buttons = WB_OK ;
+ Message [ en-US ] = "The prefix '%1' is not valid in XML. Please enter a different prefix." ;
+};
+
+ErrorBox RID_ERR_DOUBLE_MODELNAME
+{
+ Buttons = WB_OK ;
+ Message [ en-US ] = "The name '%1' already exists. Please enter a new name." ;
+};
+
+ErrorBox RID_ERR_EMPTY_SUBMISSIONNAME
+{
+ Buttons = WB_OK ;
+ Message [ en-US ] = "The submission must have a name." ;
+};
+
+ModalDialog RID_SVXDLG_ADD_DATAITEM
+{
+ HelpID = HID_XFORMS_ADDDATAITEM_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 180 , 186 ) ;
+ Moveable = TRUE ;
+ FixedLine FL_ITEM
+ {
+ Pos = MAP_APPFONT ( 4 , 3 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ Text [ en-US ] = "Item" ;
+ };
+ FixedText FT_NAME
+ {
+ Pos = MAP_APPFONT ( 6 , 15 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Name" ;
+ };
+ Edit ED_NAME
+ {
+ Pos = MAP_APPFONT ( 78 , 14 ) ;
+ Size = MAP_APPFONT ( 96 , 12 ) ;
+ Border = TRUE ;
+ };
+ FixedText FT_DEFAULT
+ {
+ Pos = MAP_APPFONT ( 6 , 30 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Default Value" ;
+ };
+ Edit ED_DEFAULT
+ {
+ Pos = MAP_APPFONT ( 78 , 29 ) ;
+ Size = MAP_APPFONT ( 96 , 12 ) ;
+ Border = TRUE ;
+ };
+ PushButton PB_DEFAULT
+ {
+ Pos = MAP_APPFONT ( 160 , 29 ) ;
+ Size = MAP_APPFONT ( 14 , 14 ) ;
+ TabStop = TRUE ;
+ Hide = TRUE ;
+ Text = "..." ;
+ };
+ FixedLine FL_SETTINGS
+ {
+ Pos = MAP_APPFONT ( 4 , 44 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ Text [ en-US ] = "Settings" ;
+ };
+ FixedText FT_DATATYPE
+ {
+ Pos = MAP_APPFONT ( 6 , 56 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Data Type" ;
+ };
+ ListBox LB_DATATYPE
+ {
+ Pos = MAP_APPFONT ( 78 , 55 ) ;
+ Size = MAP_APPFONT ( 96 , 45 ) ;
+ Border = TRUE ;
+ DropDown = TRUE;
+ };
+ CheckBox CB_REQUIRED
+ {
+ Pos = MAP_APPFONT ( 6 , 72 ) ;
+ Size = MAP_APPFONT ( 69 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Required" ;
+ };
+ PushButton PB_REQUIRED
+ {
+ Pos = MAP_APPFONT ( 78 , 70 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Condition" ;
+ };
+ CheckBox CB_RELEVANT
+ {
+ Pos = MAP_APPFONT ( 6 , 89 ) ;
+ Size = MAP_APPFONT ( 69 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "R~elevant" ;
+ };
+ PushButton PB_RELEVANT
+ {
+ Pos = MAP_APPFONT ( 78 , 87 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Condition" ;
+ };
+ CheckBox CB_CONSTRAINT
+ {
+ Pos = MAP_APPFONT ( 6 , 106 ) ;
+ Size = MAP_APPFONT ( 69 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Constraint" ;
+ };
+ PushButton PB_CONSTRAINT
+ {
+ Pos = MAP_APPFONT ( 78 , 104 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Condition" ;
+ };
+ CheckBox CB_READONLY
+ {
+ Pos = MAP_APPFONT ( 6 , 123 ) ;
+ Size = MAP_APPFONT ( 69 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Read-~only" ;
+ };
+ PushButton PB_READONLY
+ {
+ Pos = MAP_APPFONT ( 78 , 121 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Condition" ;
+ };
+ CheckBox CB_CALCULATE
+ {
+ Pos = MAP_APPFONT ( 6 , 140 ) ;
+ Size = MAP_APPFONT ( 69 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Calc~ulate" ;
+ };
+ PushButton PB_CALCULATE
+ {
+ Pos = MAP_APPFONT ( 78 , 138 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "Condition" ;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 155 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 15 , 166 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 68 , 166 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 124 , 166 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ String STR_FIXEDLINE_ELEMENT
+ {
+ Text [ en-US ] = "Element" ;
+ };
+ String STR_FIXEDLINE_ATTRIBUTE
+ {
+ Text [ en-US ] = "Attribute" ;
+ };
+ String STR_FIXEDLINE_BINDING
+ {
+ Text [ en-US ] = "Binding" ;
+ };
+ String STR_FIXEDTEXT_BINDING
+ {
+ Text [ en-US ] = "Binding expression" ;
+ };
+};
+
+Menu RID_MENU_DATANAVIGATOR
+{
+ ItemList =
+ {
+ // MID_INSERT_CONTROL not implemented, yet (#i99890#)
+ /*MenuItem
+ {
+ Identifier = MID_INSERT_CONTROL ;
+ HelpId = HID_XFORMS_MID_INSERT_CONTROL ;
+ Text [ en-US ] = "Insert Control" ;
+ };
+ MenuItem
+ {
+ Separator = TRUE;
+ };*/
+ MenuItem
+ {
+ Identifier = TBI_ITEM_ADD ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD ;
+ Text [ en-US ] = "Add Item" ;
+ };
+ MenuItem
+ {
+ Identifier = TBI_ITEM_ADD_ELEMENT ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD_ELEMENT ;
+ Text [ en-US ] = "Add Element" ;
+ };
+ MenuItem
+ {
+ Identifier = TBI_ITEM_ADD_ATTRIBUTE ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_ADD_ATTRIBUTE ;
+ Text [ en-US ] = "Add Attribute" ;
+ };
+ MenuItem
+ {
+ Identifier = TBI_ITEM_EDIT ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_EDIT ;
+ Text [ en-US ] = "Edit" ;
+ };
+ MenuItem
+ {
+ Separator = TRUE;
+ };
+ MenuItem
+ {
+ Identifier = TBI_ITEM_REMOVE ;
+ HelpId = HID_XFORMS_TOOLBOX_ITEM_REMOVE ;
+ Text [ en-US ] = "Delete" ;
+ };
+ };
+};
+
+ModalDialog RID_SVXDLG_ADD_CONDITION
+{
+ HelpID = HID_XFORMS_ADDCONDITION_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 210 , 150 ) ;
+ Text [ en-US ] = "Add Condition" ;
+ Moveable = TRUE ;
+ FixedText FT_CONDITION
+ {
+ Pos = MAP_APPFONT ( 6 , 3 ) ;
+ Size = MAP_APPFONT ( 198 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Condition" ;
+ };
+ MultiLineEdit ED_CONDITION
+ {
+ Border = TRUE ;
+ Pos = MAP_APPFONT ( 6 , 14 ) ;
+ Size = MAP_APPFONT ( 198 , 34 ) ;
+ TabStop = TRUE ;
+ Left = TRUE ;
+ IgnoreTab = TRUE;
+ };
+ FixedText FT_RESULT
+ {
+ Pos = MAP_APPFONT ( 6 , 51 ) ;
+ Size = MAP_APPFONT ( 198 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Result" ;
+ };
+ FixedText FT_RESULT_PREVIEW
+ {
+ Pos = MAP_APPFONT ( 6 , 62 ) ;
+ Size = MAP_APPFONT ( 198 , 34 ) ;
+ Border = TRUE;
+ TabStop = TRUE ;
+ Left = TRUE ;
+ WordBreak = TRUE ;
+ };
+ PushButton PB_EDIT_NAMESPACES
+ {
+ Pos = MAP_APPFONT ( 132 , 102 ) ;
+ Size = MAP_APPFONT ( 72 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Edit Namespaces..." ;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 119 ) ;
+ Size = MAP_APPFONT ( 202 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 45 , 130 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 98 , 130 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 154 , 130 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+};
+
+ModalDialog RID_SVXDLG_NAMESPACE_ITEM
+{
+ HelpID = HID_XFORMS_NAMESPACEITEM_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 240 , 120 ) ;
+ Text [ en-US ] = "Namespaces for Forms" ;
+ Moveable = TRUE ;
+ FixedText FT_NAMESPACES
+ {
+ Pos = MAP_APPFONT ( 6 , 3 ) ;
+ Size = MAP_APPFONT ( 228 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Namespaces" ;
+ };
+ Control LB_NAMESPACES
+ {
+ HelpId = HID_XFORMS_NAMESPACEITEM_LIST;
+ Pos = MAP_APPFONT ( 6 , 14 ) ;
+ Size = MAP_APPFONT ( 175 , 72 ) ;
+ Border = TRUE ;
+ TabStop = TRUE ;
+ };
+ PushButton PB_ADD_NAMESPACE
+ {
+ Pos = MAP_APPFONT ( 184 , 14 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Add..." ;
+ };
+ PushButton PB_EDIT_NAMESPACE
+ {
+ Pos = MAP_APPFONT ( 184 , 31 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Edit..." ;
+ };
+ PushButton PB_DELETE_NAMESPACE
+ {
+ Pos = MAP_APPFONT ( 184 , 48 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Delete" ;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 89 ) ;
+ Size = MAP_APPFONT ( 232 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 75 , 100 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 128 , 100 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 184 , 100 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ String STR_HEADER_PREFIX
+ {
+ Text [ en-US ] = "Prefix" ;
+ };
+ String STR_HEADER_URL
+ {
+ Text [ en-US ] = "URL" ;
+ };
+};
+
+ModalDialog RID_SVXDLG_MANAGE_NAMESPACE
+{
+ HelpID = HID_XFORMS_MANAGENAMESPACE_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 210 , 60 ) ;
+ Text [ en-US ] = "Add Namespace" ;
+ Moveable = TRUE ;
+ FixedText FT_PREFIX
+ {
+ Pos = MAP_APPFONT ( 6 , 3 ) ;
+ Size = MAP_APPFONT ( 45 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Prefix" ;
+ };
+ Edit ED_PREFIX
+ {
+ Pos = MAP_APPFONT ( 6 , 14 ) ;
+ Size = MAP_APPFONT ( 45 , 12 ) ;
+ Border = TRUE;
+ };
+ FixedText FT_URL
+ {
+ Pos = MAP_APPFONT ( 54 , 3 ) ;
+ Size = MAP_APPFONT ( 150 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~URL" ;
+ };
+ Edit ED_URL
+ {
+ Pos = MAP_APPFONT ( 54 , 14 ) ;
+ Size = MAP_APPFONT ( 150 , 12 ) ;
+ Border = TRUE;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 29 ) ;
+ Size = MAP_APPFONT ( 202 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 45 , 40 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 98 , 40 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 154 , 40 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ String STR_EDIT_TEXT
+ {
+ Text [ en-US ] = "Edit Namespace" ;
+ };
+};
+
+ModalDialog RID_SVXDLG_ADD_SUBMISSION
+{
+ HelpID = HID_XFORMS_ADDSUBMISSION_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 180 , 136 ) ;
+ Text [ en-US ] = "Add Submission" ;
+ Moveable = TRUE ;
+ FixedLine FL_SUBMISSION
+ {
+ Pos = MAP_APPFONT ( 4 , 3 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ Text [ en-US ] = "Submission" ;
+ };
+ FixedText FT_SUBMIT_NAME
+ {
+ Pos = MAP_APPFONT ( 6 , 16 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Name" ;
+ };
+ Edit ED_SUBMIT_NAME
+ {
+ Pos = MAP_APPFONT ( 78 , 14 ) ;
+ Size = MAP_APPFONT ( 96 , 12 ) ;
+ Border = TRUE ;
+ };
+ FixedText FT_SUBMIT_ACTION
+ {
+ Pos = MAP_APPFONT ( 6 , 31 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Action" ;
+ };
+ Edit ED_SUBMIT_ACTION
+ {
+ Pos = MAP_APPFONT ( 78 , 29 ) ;
+ Size = MAP_APPFONT ( 96 , 12 ) ;
+ Border = TRUE ;
+ };
+ FixedText FT_SUBMIT_METHOD
+ {
+ Pos = MAP_APPFONT ( 6 , 46 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Method" ;
+ };
+ ListBox LB_SUBMIT_METHOD
+ {
+ Pos = MAP_APPFONT ( 78 , 44 ) ;
+ Size = MAP_APPFONT ( 96 , 51 ) ;
+ Border = TRUE ;
+ DropDown = TRUE;
+ };
+ FixedText FT_SUBMIT_REF
+ {
+ Pos = MAP_APPFONT ( 6 , 62 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "Binding e~xpression" ;
+ };
+ Edit ED_SUBMIT_REF
+ {
+ Pos = MAP_APPFONT ( 78 , 60 ) ;
+ Size = MAP_APPFONT ( 79, 12 ) ;
+ Border = TRUE ;
+ };
+ PushButton PB_SUBMIT_REF
+ {
+ Pos = MAP_APPFONT ( 159 , 59 ) ;
+ Size = MAP_APPFONT ( 14 , 14 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~..." ;
+ };
+ FixedText FT_SUBMIT_BIND
+ {
+ Pos = MAP_APPFONT ( 6 , 77 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Binding" ;
+ };
+ ListBox LB_SUBMIT_BIND
+ {
+ Pos = MAP_APPFONT ( 78 , 75 ) ;
+ Size = MAP_APPFONT ( 96 , 51 ) ;
+ Border = TRUE ;
+ DropDown = TRUE;
+ };
+ FixedText FT_SUBMIT_REPLACE
+ {
+ Pos = MAP_APPFONT ( 6 , 92 ) ;
+ Size = MAP_APPFONT ( 69 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Replace" ;
+ };
+ ListBox LB_SUBMIT_REPLACE
+ {
+ Pos = MAP_APPFONT ( 78 , 90 ) ;
+ Size = MAP_APPFONT ( 96 , 51 ) ;
+ Border = TRUE ;
+ DropDown = TRUE;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 105 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 15 , 116 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 68 , 116 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 124 , 116 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+
+ String STR_METHOD_POST
+ {
+ Text [ en-US ] = "Post" ;
+ };
+ String STR_METHOD_PUT
+ {
+ Text [ en-US ] = "Put" ;
+ };
+ String STR_METHOD_GET
+ {
+ Text [ en-US ] = "Get" ;
+ };
+ String STR_REPLACE_NONE
+ {
+ Text [ en-US ] = "None" ;
+ };
+ String STR_REPLACE_INST
+ {
+ Text [ en-US ] = "Instance" ;
+ };
+ String STR_REPLACE_DOC
+ {
+ Text [ en-US ] = "Document" ;
+ };
+};
+
+ModalDialog RID_SVXDLG_ADD_MODEL
+{
+ HelpID = HID_XFORMS_ADDMODEL_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 180 , 82 ) ;
+ Text [ en-US ] = "Add Model" ;
+ Moveable = TRUE ;
+ FixedLine FL_INSTANCE
+ {
+ Pos = MAP_APPFONT ( 4 , 3 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ Text [ en-US ] = "Model" ;
+ };
+ FixedText FT_INST_NAME
+ {
+ Pos = MAP_APPFONT ( 6 , 14 ) ;
+ Size = MAP_APPFONT ( 51 , 12 ) ;
+ LeftLabel = TRUE ;
+ VCenter = TRUE;
+ Text [ en-US ] = "~Name" ;
+ };
+ Edit ED_INST_NAME
+ {
+ Pos = MAP_APPFONT ( 60 , 14 ) ;
+ Size = MAP_APPFONT ( 114 , 12 ) ;
+ Border = TRUE ;
+ };
+ CheckBox CB_MODIFIES_DOCUMENT
+ {
+ Pos = MAP_APPFONT( 6, 32 );
+ Size = MAP_APPFONT( 168, 16 );
+ Top = TRUE;
+ WordBreak = TRUE;
+
+ Text [ en-US ] = "Model data updates change document's modification status";
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 51 ) ;
+ Size = MAP_APPFONT ( 172 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 15 , 62 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 68 , 62 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 124 , 62 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ String STR_EDIT_TEXT
+ {
+ Text [ en-US ] = "Edit Model" ;
+ };
+};
+
+ModalDialog RID_SVXDLG_ADD_INSTANCE
+{
+ HelpID = HID_XFORMS_ADDINSTANCE_DLG ;
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 210 , 88 ) ;
+ Text [ en-US ] = "Add Instance" ;
+ Moveable = TRUE ;
+ FixedLine FL_INSTANCE
+ {
+ Pos = MAP_APPFONT ( 4 , 3 ) ;
+ Size = MAP_APPFONT ( 202 , 8 ) ;
+ Text [ en-US ] = "Instance" ;
+ };
+ FixedText FT_INST_NAME
+ {
+ Pos = MAP_APPFONT ( 6 , 15 ) ;
+ Size = MAP_APPFONT ( 51 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~Name" ;
+ };
+ Edit ED_INST_NAME
+ {
+ Pos = MAP_APPFONT ( 60 , 14 ) ;
+ Size = MAP_APPFONT ( 144 , 12 ) ;
+ Border = TRUE ;
+ };
+ FixedText FT_INST_URL
+ {
+ Pos = MAP_APPFONT ( 6 , 30 ) ;
+ Size = MAP_APPFONT ( 51 , 8 ) ;
+ LeftLabel = TRUE ;
+ Text [ en-US ] = "~URL" ;
+ };
+ ComboBox ED_INST_URL
+ {
+ Pos = MAP_APPFONT ( 60 , 29 ) ;
+ Size = MAP_APPFONT ( 127 , 48 ) ;
+ DropDown = TRUE ;
+ Border = TRUE ;
+ };
+ PushButton PB_FILEPICKER
+ {
+ Pos = MAP_APPFONT ( 190 , 28 ) ;
+ Size = MAP_APPFONT ( 14 , 14 ) ;
+ TabStop = TRUE ;
+ Text = "~..." ;
+ };
+ CheckBox CB_INST_LINKINST
+ {
+ Pos = MAP_APPFONT ( 6 , 44 ) ;
+ Size = MAP_APPFONT ( 198 , 10 ) ;
+ TabStop = TRUE ;
+ Text [ en-US ] = "~Link instance" ;
+ };
+ FixedLine FL_DATANAV_BTN
+ {
+ Pos = MAP_APPFONT ( 4 , 57 ) ;
+ Size = MAP_APPFONT ( 202 , 8 ) ;
+ };
+ OKButton BTN_DATANAV_OK
+ {
+ Pos = MAP_APPFONT ( 45 , 68 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_DATANAV_ESC
+ {
+ Pos = MAP_APPFONT ( 98 , 68 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_DATANAV_HELP
+ {
+ Pos = MAP_APPFONT ( 154 , 68 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ String STR_EDIT_TEXT
+ {
+ Text [ en-US ] = "Edit Instance" ;
+ };
+};
+
+String RID_STR_DATANAV_SUBM_PARENT
+{
+ Text [ en-US ] = "Submission: " ;
+};
+String RID_STR_DATANAV_SUBM_ID
+{
+ Text [ en-US ] = "ID: " ;
+};
+String RID_STR_DATANAV_SUBM_BIND
+{
+ Text [ en-US ] = "Binding: " ;
+};
+String RID_STR_DATANAV_SUBM_REF
+{
+ Text [ en-US ] = "Reference: " ;
+};
+String RID_STR_DATANAV_SUBM_ACTION
+{
+ Text [ en-US ] = "Action: " ;
+};
+String RID_STR_DATANAV_SUBM_METHOD
+{
+ Text [ en-US ] = "Method: " ;
+};
+String RID_STR_DATANAV_SUBM_REPLACE
+{
+ Text [ en-US ] = "Replace: " ;
+};
+String RID_STR_DATANAV_ADD_ELEMENT
+{
+ Text [ en-US ] = "Add Element" ;
+};
+String RID_STR_DATANAV_EDIT_ELEMENT
+{
+ Text [ en-US ] = "Edit Element" ;
+};
+String RID_STR_DATANAV_REMOVE_ELEMENT
+{
+ Text [ en-US ] = "Delete Element" ;
+};
+String RID_STR_DATANAV_ADD_ATTRIBUTE
+{
+ Text [ en-US ] = "Add Attribute" ;
+};
+String RID_STR_DATANAV_EDIT_ATTRIBUTE
+{
+ Text [ en-US ] = "Edit Attribute" ;
+};
+String RID_STR_DATANAV_REMOVE_ATTRIBUTE
+{
+ Text [ en-US ] = "Delete Attribute" ;
+};
+String RID_STR_DATANAV_ADD_BINDING
+{
+ Text [ en-US ] = "Add Binding" ;
+};
+String RID_STR_DATANAV_EDIT_BINDING
+{
+ Text [ en-US ] = "Edit Binding" ;
+};
+String RID_STR_DATANAV_REMOVE_BINDING
+{
+ Text [ en-US ] = "Delete Binding" ;
+};
+String RID_STR_DATANAV_ADD_SUBMISSION
+{
+ Text [ en-US ] = "Add Submission" ;
+};
+String RID_STR_DATANAV_EDIT_SUBMISSION
+{
+ Text [ en-US ] = "Edit Submission" ;
+};
+String RID_STR_DATANAV_REMOVE_SUBMISSION
+{
+ Text [ en-US ] = "Delete Submission" ;
+};
+String RID_STR_DATANAV_LINKWARN_BUTTON
+{
+ Text [ en-US ] = "~Edit" ;
+};
+
diff --git a/svx/source/form/dbcharsethelper.cxx b/svx/source/form/dbcharsethelper.cxx
new file mode 100644
index 000000000000..f77e95b49a5e
--- /dev/null
+++ b/svx/source/form/dbcharsethelper.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "svx/dbcharsethelper.hxx"
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ //====================================================================
+ //= ODataAccessCharsetHelper
+ //====================================================================
+ //--------------------------------------------------------------------
+ ODataAccessCharsetHelper::ODataAccessCharsetHelper( )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool ODataAccessCharsetHelper::ensureLoaded() const
+ {
+ if ( !ODbtoolsClient::ensureLoaded() )
+ return false;
+ m_xCharsetHelper = getFactory()->createCharsetHelper( );
+ return m_xCharsetHelper.is();
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/dbtoolsclient.cxx b/svx/source/form/dbtoolsclient.cxx
new file mode 100644
index 000000000000..62d283ab3a7a
--- /dev/null
+++ b/svx/source/form/dbtoolsclient.cxx
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include "svx/dbtoolsclient.hxx"
+#include <osl/diagnose.h>
+#include <connectivity/formattedcolumnvalue.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::connectivity::simple;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::container;
+
+ //====================================================================
+ //= ODbtoolsClient
+ //====================================================================
+ ::osl::Mutex ODbtoolsClient::s_aMutex;
+ sal_Int32 ODbtoolsClient::s_nClients = 0;
+ oslModule ODbtoolsClient::s_hDbtoolsModule = NULL;
+ createDataAccessToolsFactoryFunction
+ ODbtoolsClient::s_pFactoryCreationFunc = NULL;
+
+ //--------------------------------------------------------------------
+ ODbtoolsClient::ODbtoolsClient()
+ {
+ m_bCreateAlready = FALSE;
+ }
+
+ //--------------------------------------------------------------------
+ bool ODbtoolsClient::ensureLoaded() const
+ {
+ if ( !m_bCreateAlready )
+ {
+ m_bCreateAlready = true;
+
+ registerClient();
+ if ( s_pFactoryCreationFunc )
+ { // loading the lib succeeded
+ void* pUntypedFactory = (*s_pFactoryCreationFunc)();
+ IDataAccessToolsFactory* pDBTFactory = static_cast< IDataAccessToolsFactory* >( pUntypedFactory );
+ OSL_ENSURE( pDBTFactory, "ODbtoolsClient::ODbtoolsClient: no factory returned!" );
+ if ( pDBTFactory )
+ {
+ m_xDataAccessFactory = pDBTFactory;
+ // by definition, the factory was aquired once
+ m_xDataAccessFactory->release();
+ }
+ }
+ }
+ return m_xDataAccessFactory.is();
+ }
+
+ //--------------------------------------------------------------------
+ ODbtoolsClient::~ODbtoolsClient()
+ {
+ // clear the factory _before_ revoking the client
+ // (the revocation may unload the DBT lib)
+ m_xDataAccessFactory = NULL;
+ // revoke the client
+ if ( m_bCreateAlready )
+ revokeClient();
+ }
+
+ //--------------------------------------------------------------------
+ extern "C" { static void SAL_CALL thisModule() {} }
+
+ void ODbtoolsClient::registerClient()
+ {
+ ::osl::MutexGuard aGuard(s_aMutex);
+ if (1 == ++s_nClients)
+ {
+ OSL_ENSURE(NULL == s_hDbtoolsModule, "ODbtoolsClient::registerClient: inconsistence: already have a module!");
+ OSL_ENSURE(NULL == s_pFactoryCreationFunc, "ODbtoolsClient::registerClient: inconsistence: already have a factory function!");
+
+ const ::rtl::OUString sModuleName(RTL_CONSTASCII_USTRINGPARAM(
+ SVLIBRARY( "dbtools" ))
+ );
+
+ // load the dbtools library
+ s_hDbtoolsModule = osl_loadModuleRelative(
+ &thisModule, sModuleName.pData, 0);
+ OSL_ENSURE(NULL != s_hDbtoolsModule, "ODbtoolsClient::registerClient: could not load the dbtools library!");
+ if (NULL != s_hDbtoolsModule)
+ {
+ // get the symbol for the method creating the factory
+ const ::rtl::OUString sFactoryCreationFunc( RTL_CONSTASCII_USTRINGPARAM("createDataAccessToolsFactory") );
+ // reinterpret_cast<createDataAccessToolsFactoryFunction>
+ s_pFactoryCreationFunc = (createDataAccessToolsFactoryFunction)(
+ osl_getFunctionSymbol(s_hDbtoolsModule, sFactoryCreationFunc.pData));
+
+ if (NULL == s_pFactoryCreationFunc)
+ { // did not find the symbol
+ OSL_ENSURE(sal_False, "ODbtoolsClient::registerClient: could not find the symbol for creating the factory!");
+ osl_unloadModule(s_hDbtoolsModule);
+ s_hDbtoolsModule = NULL;
+ }
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ODbtoolsClient::revokeClient()
+ {
+ ::osl::MutexGuard aGuard(s_aMutex);
+ if (0 == --s_nClients)
+ {
+ s_pFactoryCreationFunc = NULL;
+ if (s_hDbtoolsModule)
+ osl_unloadModule(s_hDbtoolsModule);
+ s_hDbtoolsModule = NULL;
+ }
+
+ OSL_ENSURE(s_nClients >= 0,"Illegall call of revokeClient()");
+ }
+
+ //====================================================================
+ //= OStaticDataAccessTools
+ //====================================================================
+ //--------------------------------------------------------------------
+ OStaticDataAccessTools::OStaticDataAccessTools()
+ {
+ }
+
+ //--------------------------------------------------------------------
+
+ bool OStaticDataAccessTools::ensureLoaded() const
+ {
+ if ( !ODbtoolsClient::ensureLoaded() )
+ return false;
+ m_xDataAccessTools = getFactory()->getDataAccessTools();
+ return m_xDataAccessTools.is();
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XNumberFormatsSupplier > OStaticDataAccessTools::getNumberFormats(const Reference< XConnection>& _rxConn, sal_Bool _bAllowDefault) const
+ {
+ Reference< XNumberFormatsSupplier > xReturn;
+ if ( ensureLoaded() )
+ xReturn = m_xDataAccessTools->getNumberFormats(_rxConn, _bAllowDefault);
+ return xReturn;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 OStaticDataAccessTools::getDefaultNumberFormat( const Reference< XPropertySet >& _xColumn, const Reference< XNumberFormatTypes >& _xTypes, const Locale& _rLocale )
+ {
+ sal_Int32 nReturn = 0;
+ if ( ensureLoaded() )
+ nReturn = m_xDataAccessTools->getDefaultNumberFormat( _xColumn, _xTypes, _rLocale );
+ return nReturn;
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XConnection> OStaticDataAccessTools::getConnection_withFeedback(const ::rtl::OUString& _rDataSourceName,
+ const ::rtl::OUString& _rUser, const ::rtl::OUString& _rPwd, const Reference< XMultiServiceFactory>& _rxFactory) const
+ SAL_THROW ( (SQLException) )
+ {
+ Reference< XConnection > xReturn;
+ if ( ensureLoaded() )
+ xReturn = m_xDataAccessTools->getConnection_withFeedback(_rDataSourceName, _rUser, _rPwd, _rxFactory);
+ return xReturn;
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XConnection > OStaticDataAccessTools::connectRowset( const Reference< XRowSet >& _rxRowSet,
+ const Reference< XMultiServiceFactory >& _rxFactory, sal_Bool _bSetAsActiveConnection ) const
+ SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) )
+ {
+ Reference< XConnection > xReturn;
+ if ( ensureLoaded() )
+ xReturn = m_xDataAccessTools->connectRowset( _rxRowSet, _rxFactory, _bSetAsActiveConnection );
+ return xReturn;
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XConnection > OStaticDataAccessTools::getRowSetConnection(const Reference< XRowSet >& _rxRowSet) const SAL_THROW ( (RuntimeException) )
+ {
+ Reference< XConnection > xReturn;
+ if ( ensureLoaded() )
+ xReturn = m_xDataAccessTools->getRowSetConnection(_rxRowSet);
+ return xReturn;
+ }
+
+ //--------------------------------------------------------------------
+ void OStaticDataAccessTools::TransferFormComponentProperties(const Reference< XPropertySet>& _rxOld,
+ const Reference< XPropertySet>& _rxNew, const Locale& _rLocale) const
+ {
+ if ( ensureLoaded() )
+ m_xDataAccessTools->TransferFormComponentProperties(_rxOld, _rxNew, _rLocale);
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OStaticDataAccessTools::quoteName(const ::rtl::OUString& _rQuote, const ::rtl::OUString& _rName) const
+ {
+ ::rtl::OUString sReturn;
+ if ( ensureLoaded() )
+ sReturn = m_xDataAccessTools->quoteName(_rQuote, _rName);
+ return sReturn;
+ }
+
+ // ------------------------------------------------
+ ::rtl::OUString OStaticDataAccessTools::composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference< XPropertySet>& _xTable ) const
+ {
+ ::rtl::OUString sReturn;
+ if ( ensureLoaded() )
+ sReturn = m_xDataAccessTools->composeTableNameForSelect( _rxConnection, _xTable );
+ return sReturn;
+ }
+
+ //--------------------------------------------------------------------
+ SQLContext OStaticDataAccessTools::prependContextInfo(SQLException& _rException, const Reference< XInterface >& _rxContext,
+ const ::rtl::OUString& _rContextDescription, const ::rtl::OUString& _rContextDetails) const
+ {
+ SQLContext aReturn;
+ if ( ensureLoaded() )
+ aReturn = m_xDataAccessTools->prependContextInfo(_rException, _rxContext, _rContextDescription, _rContextDetails);
+ return aReturn;
+ }
+
+ //----------------------------------------------------------------
+ Reference< XDataSource > OStaticDataAccessTools::getDataSource( const ::rtl::OUString& _rsRegisteredName, const Reference< XMultiServiceFactory>& _rxFactory ) const
+ {
+ Reference< XDataSource > xReturn;
+ if ( ensureLoaded() )
+ xReturn = m_xDataAccessTools->getDataSource(_rsRegisteredName,_rxFactory);
+ return xReturn;
+ }
+
+ //----------------------------------------------------------------
+ sal_Bool OStaticDataAccessTools::canInsert(const Reference< XPropertySet>& _rxCursorSet) const
+ {
+ sal_Bool bRet = sal_False;
+ if ( ensureLoaded() )
+ bRet = m_xDataAccessTools->canInsert( _rxCursorSet );
+ return bRet;
+ }
+
+ //----------------------------------------------------------------
+ sal_Bool OStaticDataAccessTools::canUpdate(const Reference< XPropertySet>& _rxCursorSet) const
+ {
+ sal_Bool bRet = sal_False;
+ if ( ensureLoaded() )
+ bRet = m_xDataAccessTools->canUpdate( _rxCursorSet );
+ return bRet;
+ }
+
+ //----------------------------------------------------------------
+ sal_Bool OStaticDataAccessTools::canDelete(const Reference< XPropertySet>& _rxCursorSet) const
+ {
+ sal_Bool bRet = sal_False;
+ if ( ensureLoaded() )
+ bRet = m_xDataAccessTools->canDelete( _rxCursorSet );
+ return bRet;
+ }
+
+ //----------------------------------------------------------------
+ Reference< XNameAccess > OStaticDataAccessTools::getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection,
+ const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand,
+ Reference< XComponent >& _rxKeepFieldsAlive, ::dbtools::SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
+ {
+ Reference< XNameAccess > aFields;
+ if ( ensureLoaded() )
+ aFields = m_xDataAccessTools->getFieldsByCommandDescriptor( _rxConnection, _nCommandType,
+ _rCommand, _rxKeepFieldsAlive, _pErrorInfo );
+
+ return aFields;
+ }
+
+ //----------------------------------------------------------------
+ Sequence< ::rtl::OUString > OStaticDataAccessTools::getFieldNamesByCommandDescriptor(
+ const Reference< XConnection >& _rxConnection, const sal_Int32 _nCommandType,
+ const ::rtl::OUString& _rCommand, ::dbtools::SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) )
+ {
+ Sequence< ::rtl::OUString > aNames;
+ if ( ensureLoaded() )
+ aNames = m_xDataAccessTools->getFieldNamesByCommandDescriptor( _rxConnection, _nCommandType,
+ _rCommand, _pErrorInfo );
+ return aNames;
+ }
+
+ //----------------------------------------------------------------
+ bool OStaticDataAccessTools::isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection )
+ {
+ bool bReturn = false;
+ if ( ensureLoaded() )
+ bReturn = m_xDataAccessTools->isEmbeddedInDatabase( _rxComponent, _rxActualConnection );
+ return bReturn;
+ }
+
+ //----------------------------------------------------------------
+ bool OStaticDataAccessTools::isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent )
+ {
+ bool bReturn = false;
+ if ( ensureLoaded() )
+ {
+ Reference< XConnection > xDummy;
+ bReturn = m_xDataAccessTools->isEmbeddedInDatabase( _rxComponent, xDummy );
+ }
+ return bReturn;
+ }
+
+ //====================================================================
+ //= DBToolsObjectFactory
+ //====================================================================
+ //----------------------------------------------------------------
+ DBToolsObjectFactory::DBToolsObjectFactory()
+ {
+ }
+
+ //----------------------------------------------------------------
+ DBToolsObjectFactory::~DBToolsObjectFactory()
+ {
+ }
+
+ //----------------------------------------------------------------
+ ::std::auto_ptr< ::dbtools::FormattedColumnValue > DBToolsObjectFactory::createFormattedColumnValue(
+ const ::comphelper::ComponentContext& _rContext, const Reference< XRowSet >& _rxRowSet, const Reference< XPropertySet >& _rxColumn )
+ {
+ ::std::auto_ptr< ::dbtools::FormattedColumnValue > pValue;
+ if ( ensureLoaded() )
+ pValue = getFactory()->createFormattedColumnValue( _rContext, _rxRowSet, _rxColumn );
+ return pValue;
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/delayedevent.cxx b/svx/source/form/delayedevent.cxx
new file mode 100644
index 000000000000..182e64788aed
--- /dev/null
+++ b/svx/source/form/delayedevent.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+************************************************************************/
+
+#include "precompiled_svx.hxx"
+
+#include "delayedevent.hxx"
+
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ //====================================================================
+ //= DelayedEvent
+ //====================================================================
+ //--------------------------------------------------------------------
+ void DelayedEvent::Call( void* _pArg )
+ {
+ CancelPendingCall();
+ OSL_POSTCOND( m_nEventId == 0, "DelayedEvent::Call: CancelPendingCall did not work!" );
+
+ m_nEventId = Application::PostUserEvent( LINK( this, DelayedEvent, OnCall ), _pArg );
+ }
+
+ //--------------------------------------------------------------------
+ void DelayedEvent::CancelPendingCall()
+ {
+ if ( m_nEventId )
+ Application::RemoveUserEvent( m_nEventId );
+ m_nEventId = 0;
+ }
+
+ //--------------------------------------------------------------------
+ IMPL_LINK( DelayedEvent, OnCall, void*, _pArg )
+ {
+ m_nEventId = 0;
+ return m_aHandler.Call( _pArg );
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/filtnav.cxx b/svx/source/form/filtnav.cxx
new file mode 100644
index 000000000000..8c6bba3ace1f
--- /dev/null
+++ b/svx/source/form/filtnav.cxx
@@ -0,0 +1,2064 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+
+#include "filtnav.hxx"
+#include "fmexch.hxx"
+#include "fmhelp.hrc"
+#include "fmitems.hxx"
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/XTextComponent.hpp>
+#include <com/sun/star/form/runtime/XFormController.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/processfactory.hxx>
+#include <svx/fmtools.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <fmservs.hxx>
+#include <fmshimp.hxx>
+#include <rtl/logfile.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/request.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/svxids.hrc>
+#include <tools/shl.hxx>
+#include <vcl/wrkwin.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <functional>
+
+#define SYNC_DELAY 200
+#define DROP_ACTION_TIMER_INITIAL_TICKS 10
+ // solange dauert es, bis das Scrollen anspringt
+#define DROP_ACTION_TIMER_SCROLL_TICKS 3
+ // in diesen Intervallen wird jeweils eine Zeile gescrollt
+#define DROP_ACTION_TIMER_TICK_BASE 10
+ // das ist die Basis, mit der beide Angaben multipliziert werden (in ms)
+
+using namespace ::svxform;
+using namespace ::connectivity::simple;
+using namespace ::connectivity;
+
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::awt::TextEvent;
+ using ::com::sun::star::container::XIndexAccess;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::form::runtime::XFormController;
+ using ::com::sun::star::form::runtime::XFilterController;
+ using ::com::sun::star::form::runtime::XFilterControllerListener;
+ using ::com::sun::star::form::runtime::FilterEvent;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::form::XForm;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::awt::XControl;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::util::XNumberFormatter;
+ using ::com::sun::star::sdbc::XRowSet;
+ using ::com::sun::star::lang::Locale;
+ using ::com::sun::star::sdb::SQLContext;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::awt::XTextComponent;
+ using ::com::sun::star::uno::Sequence;
+ /** === end UNO using === **/
+
+//========================================================================
+OFilterItemExchange::OFilterItemExchange()
+{
+}
+
+//------------------------------------------------------------------------
+void OFilterItemExchange::AddSupportedFormats()
+{
+ AddFormat(getFormatId());
+}
+
+//------------------------------------------------------------------------
+sal_uInt32 OFilterItemExchange::getFormatId()
+{
+ static sal_uInt32 s_nFormat = (sal_uInt32)-1;
+ if ((sal_uInt32)-1 == s_nFormat)
+ {
+ s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"form.FilterControlExchange\""));
+ DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OFilterExchangeHelper::getFormatId: bad exchange id!");
+ }
+ return s_nFormat;
+}
+
+//------------------------------------------------------------------------
+OLocalExchange* OFilterExchangeHelper::createExchange() const
+{
+ return new OFilterItemExchange;
+}
+
+//========================================================================
+TYPEINIT0(FmFilterData);
+Image FmFilterData::GetImage( BmpColorMode /*_eMode*/ ) const
+{
+ return Image();
+}
+
+//========================================================================
+TYPEINIT1(FmParentData, FmFilterData);
+//------------------------------------------------------------------------
+FmParentData::~FmParentData()
+{
+ for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
+ i != m_aChildren.end(); i++)
+ delete (*i);
+}
+
+//========================================================================
+TYPEINIT1(FmFormItem, FmParentData);
+//------------------------------------------------------------------------
+Image FmFormItem::GetImage( BmpColorMode /* _eMode */) const
+{
+ static Image aImage;
+
+ if (!aImage)
+ {
+ ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
+ aImage = aNavigatorImages.GetImage( RID_SVXIMG_FORM );
+ }
+ return aImage;
+}
+
+//========================================================================
+TYPEINIT1(FmFilterItems, FmParentData);
+//------------------------------------------------------------------------
+FmFilterItem* FmFilterItems::Find( const ::sal_Int32 _nFilterComponentIndex ) const
+{
+ for ( ::std::vector< FmFilterData* >::const_iterator i = m_aChildren.begin();
+ i != m_aChildren.end();
+ ++i
+ )
+ {
+ FmFilterItem* pCondition = PTR_CAST( FmFilterItem, *i );
+ DBG_ASSERT( pCondition, "FmFilterItems::Find: Wrong element in container!" );
+ if ( _nFilterComponentIndex == pCondition->GetComponentIndex() )
+ return pCondition;
+ }
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+Image FmFilterItems::GetImage( BmpColorMode /* _eMode */ ) const
+{
+ static Image aImage;
+
+ if (!aImage)
+ {
+ ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
+ aImage = aNavigatorImages.GetImage( RID_SVXIMG_FILTER );
+ }
+ return aImage;
+}
+
+//========================================================================
+TYPEINIT1(FmFilterItem, FmFilterData);
+//------------------------------------------------------------------------
+FmFilterItem::FmFilterItem( const Reference< XMultiServiceFactory >& _rxFactory,
+ FmFilterItems* pParent,
+ const ::rtl::OUString& aFieldName,
+ const ::rtl::OUString& aText,
+ const sal_Int32 _nComponentIndex )
+ :FmFilterData(_rxFactory,pParent, aText)
+ ,m_aFieldName(aFieldName)
+ ,m_nComponentIndex( _nComponentIndex )
+{
+}
+
+//------------------------------------------------------------------------
+Image FmFilterItem::GetImage( BmpColorMode /* _eMode */ ) const
+{
+ static Image aImage;
+
+ if (!aImage)
+ {
+ ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
+ aImage = aNavigatorImages.GetImage( RID_SVXIMG_FIELD );
+ }
+ return aImage;
+}
+
+//========================================================================
+// Hints for communicatition between model and view
+//========================================================================
+class FmFilterHint : public SfxHint
+{
+ FmFilterData* m_pData;
+
+public:
+ TYPEINFO();
+ FmFilterHint(FmFilterData* pData):m_pData(pData){}
+ FmFilterData* GetData() const { return m_pData; }
+};
+TYPEINIT1( FmFilterHint, SfxHint );
+
+//========================================================================
+class FmFilterInsertedHint : public FmFilterHint
+{
+ sal_Int32 m_nPos; // Position relative to the parent of the data
+
+public:
+ TYPEINFO();
+ FmFilterInsertedHint(FmFilterData* pData, sal_Int32 nRelPos)
+ :FmFilterHint(pData)
+ ,m_nPos(nRelPos){}
+
+ sal_Int32 GetPos() const { return m_nPos; }
+};
+TYPEINIT1( FmFilterInsertedHint, FmFilterHint );
+
+//========================================================================
+class FmFilterRemovedHint : public FmFilterHint
+{
+public:
+ TYPEINFO();
+ FmFilterRemovedHint(FmFilterData* pData)
+ :FmFilterHint(pData){}
+
+};
+TYPEINIT1( FmFilterRemovedHint, FmFilterHint );
+
+//========================================================================
+class FmFilterTextChangedHint : public FmFilterHint
+{
+public:
+ TYPEINFO();
+ FmFilterTextChangedHint(FmFilterData* pData)
+ :FmFilterHint(pData){}
+
+};
+TYPEINIT1( FmFilterTextChangedHint, FmFilterHint );
+
+//========================================================================
+class FilterClearingHint : public SfxHint
+{
+public:
+ TYPEINFO();
+ FilterClearingHint(){}
+};
+TYPEINIT1( FilterClearingHint, SfxHint );
+
+//========================================================================
+class FmFilterCurrentChangedHint : public SfxHint
+{
+public:
+ TYPEINFO();
+ FmFilterCurrentChangedHint(){}
+};
+TYPEINIT1( FmFilterCurrentChangedHint, SfxHint );
+
+//========================================================================
+// class FmFilterAdapter, Listener an den FilterControls
+//========================================================================
+class FmFilterAdapter : public ::cppu::WeakImplHelper1< XFilterControllerListener >
+{
+ FmFilterModel* m_pModel;
+ Reference< XIndexAccess > m_xControllers;
+
+public:
+ FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers);
+
+// XEventListener
+ virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
+
+// XFilterControllerListener
+ virtual void SAL_CALL predicateExpressionChanged( const FilterEvent& _Event ) throw (RuntimeException);
+ virtual void SAL_CALL disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException);
+ virtual void SAL_CALL disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException);
+
+// helpers
+ void dispose() throw( RuntimeException );
+
+ void AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd );
+
+ void setText(sal_Int32 nPos,
+ const FmFilterItem* pFilterItem,
+ const ::rtl::OUString& rText);
+};
+
+//------------------------------------------------------------------------
+FmFilterAdapter::FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers)
+ :m_pModel( pModel )
+ ,m_xControllers( xControllers )
+{
+ AddOrRemoveListener( m_xControllers, true );
+}
+
+//------------------------------------------------------------------------
+void FmFilterAdapter::dispose() throw( RuntimeException )
+{
+ AddOrRemoveListener( m_xControllers, false );
+}
+
+//------------------------------------------------------------------------
+void FmFilterAdapter::AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd )
+{
+ for (sal_Int32 i = 0, nLen = _rxControllers->getCount(); i < nLen; ++i)
+ {
+ Reference< XIndexAccess > xElement( _rxControllers->getByIndex(i), UNO_QUERY );
+
+ // step down
+ AddOrRemoveListener( xElement, _bAdd );
+
+ // handle this particular controller
+ Reference< XFilterController > xController( xElement, UNO_QUERY );
+ OSL_ENSURE( xController.is(), "FmFilterAdapter::InsertElements: no XFilterController, cannot sync data!" );
+ if ( xController.is() )
+ {
+ if ( _bAdd )
+ xController->addFilterControllerListener( this );
+ else
+ xController->removeFilterControllerListener( this );
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFilterAdapter::setText(sal_Int32 nRowPos,
+ const FmFilterItem* pFilterItem,
+ const ::rtl::OUString& rText)
+{
+ FmFormItem* pFormItem = PTR_CAST( FmFormItem, pFilterItem->GetParent()->GetParent() );
+
+ try
+ {
+ Reference< XFilterController > xController( pFormItem->GetController(), UNO_QUERY_THROW );
+ xController->setPredicateExpression( pFilterItem->GetComponentIndex(), nRowPos, rText );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+
+// XEventListener
+//------------------------------------------------------------------------
+void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/) throw( RuntimeException )
+{
+}
+
+//------------------------------------------------------------------------
+namespace
+{
+ ::rtl::OUString lcl_getLabelName_nothrow( const Reference< XControl >& _rxControl )
+ {
+ ::rtl::OUString sLabelName;
+ try
+ {
+ Reference< XControl > xControl( _rxControl, UNO_SET_THROW );
+ Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY_THROW );
+ sLabelName = getLabelName( xModel );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return sLabelName;
+ }
+
+ Reference< XPropertySet > lcl_getBoundField_nothrow( const Reference< XControl >& _rxControl )
+ {
+ Reference< XPropertySet > xField;
+ try
+ {
+ Reference< XControl > xControl( _rxControl, UNO_SET_THROW );
+ Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
+ xField.set( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return xField;
+ }
+}
+
+// XFilterControllerListener
+//------------------------------------------------------------------------
+void FmFilterAdapter::predicateExpressionChanged( const FilterEvent& _Event ) throw( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ if ( !m_pModel )
+ return;
+
+ // the controller which sent the event
+ Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
+
+ FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
+ OSL_ENSURE( pFormItem, "FmFilterAdapter::predicateExpressionChanged: don't know this form!" );
+ if ( !pFormItem )
+ return;
+
+ const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
+
+ FmFilterItems* pFilter = PTR_CAST( FmFilterItems, pFormItem->GetChildren()[ nActiveTerm ] );
+ FmFilterItem* pFilterItem = pFilter->Find( _Event.FilterComponent );
+ if ( pFilterItem )
+ {
+ if ( _Event.PredicateExpression.getLength())
+ {
+ pFilterItem->SetText( _Event.PredicateExpression );
+ // UI benachrichtigen
+ FmFilterTextChangedHint aChangeHint(pFilterItem);
+ m_pModel->Broadcast( aChangeHint );
+ }
+ else
+ {
+ // no text anymore so remove the condition
+ m_pModel->Remove(pFilterItem);
+ }
+ }
+ else
+ {
+ // searching the component by field name
+ ::rtl::OUString aFieldName( lcl_getLabelName_nothrow( xFilterController->getFilterComponent( _Event.FilterComponent ) ) );
+
+ pFilterItem = new FmFilterItem( m_pModel->getORB(), pFilter, aFieldName, _Event.PredicateExpression, _Event.FilterComponent );
+ m_pModel->Insert(pFilter->GetChildren().end(), pFilterItem);
+ }
+
+ // ensure there's one empty term in the filter, just in case the active term was previously empty
+ m_pModel->EnsureEmptyFilterRows( *pFormItem );
+}
+
+//------------------------------------------------------------------------
+void SAL_CALL FmFilterAdapter::disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
+
+ FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
+ OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermRemoved: don't know this form!" );
+ if ( !pFormItem )
+ return;
+
+ ::std::vector< FmFilterData* >& rTermItems = pFormItem->GetChildren();
+ const bool bValidIndex = ( _Event.DisjunctiveTerm >= 0 ) && ( (size_t)_Event.DisjunctiveTerm < rTermItems.size() );
+ OSL_ENSURE( bValidIndex, "FmFilterAdapter::disjunctiveTermRemoved: invalid term index!" );
+ if ( !bValidIndex )
+ return;
+
+ // if the first term was removed, then the to-be first term needs its text updated
+ if ( _Event.DisjunctiveTerm == 0 )
+ {
+ rTermItems[1]->SetText( String( SVX_RES( RID_STR_FILTER_FILTER_FOR ) ) );
+ FmFilterTextChangedHint aChangeHint( rTermItems[1] );
+ m_pModel->Broadcast( aChangeHint );
+ }
+
+ // finally remove the entry from the model
+ m_pModel->Remove( rTermItems.begin() + _Event.DisjunctiveTerm );
+
+ // ensure there's one empty term in the filter, just in case the currently removed one was the last empty one
+ m_pModel->EnsureEmptyFilterRows( *pFormItem );
+}
+
+//------------------------------------------------------------------------
+void SAL_CALL FmFilterAdapter::disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
+ Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
+
+ FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
+ OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermAdded: don't know this form!" );
+ if ( !pFormItem )
+ return;
+
+ const sal_Int32 nInsertPos = _Event.DisjunctiveTerm;
+ bool bValidIndex = ( nInsertPos >= 0 ) && ( (size_t)nInsertPos <= pFormItem->GetChildren().size() );
+ if ( !bValidIndex )
+ {
+ OSL_ENSURE( false, "FmFilterAdapter::disjunctiveTermAdded: invalid index!" );
+ return;
+ }
+
+ const ::std::vector< FmFilterData* >::iterator insertPos = pFormItem->GetChildren().begin() + nInsertPos;
+
+ FmFilterItems* pFilterItems = new FmFilterItems( m_pModel->getORB(), pFormItem, String( SVX_RES( RID_STR_FILTER_FILTER_OR ) ) );
+ m_pModel->Insert( insertPos, pFilterItems );
+}
+
+//========================================================================
+// class FmFilterModel
+//========================================================================
+TYPEINIT1(FmFilterModel, FmParentData);
+//------------------------------------------------------------------------
+FmFilterModel::FmFilterModel(const Reference< XMultiServiceFactory >& _rxFactory)
+ :FmParentData(_rxFactory,NULL, ::rtl::OUString())
+ ,OSQLParserClient(_rxFactory)
+ ,m_xORB(_rxFactory)
+ ,m_pAdapter(NULL)
+ ,m_pCurrentItems(NULL)
+{
+}
+
+//------------------------------------------------------------------------
+FmFilterModel::~FmFilterModel()
+{
+ Clear();
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Clear()
+{
+ // notify
+ FilterClearingHint aClearedHint;
+ Broadcast( aClearedHint );
+
+ // loose endings
+ if (m_pAdapter)
+ {
+ m_pAdapter->dispose();
+ m_pAdapter->release();
+ m_pAdapter= NULL;
+ }
+
+ m_pCurrentItems = NULL;
+ m_xController = NULL;
+ m_xControllers = NULL;
+
+ for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
+ i != m_aChildren.end(); i++)
+ delete (*i);
+
+ m_aChildren.clear();
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
+{
+ if ( xCurrent == m_xController )
+ return;
+
+ if (!xControllers.is())
+ {
+ Clear();
+ return;
+ }
+
+ // there is only a new current controller
+ if ( m_xControllers != xControllers )
+ {
+ Clear();
+
+ m_xControllers = xControllers;
+ Update(m_xControllers, this);
+
+ DBG_ASSERT(xCurrent.is(), "FmFilterModel::Update(...) no current controller");
+
+ // Listening for TextChanges
+ m_pAdapter = new FmFilterAdapter(this, xControllers);
+ m_pAdapter->acquire();
+
+ SetCurrentController(xCurrent);
+ EnsureEmptyFilterRows( *this );
+ }
+ else
+ SetCurrentController(xCurrent);
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, FmParentData* pParent)
+{
+ try
+ {
+ sal_Int32 nCount = xControllers->getCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Reference< XFormController > xController( xControllers->getByIndex(i), UNO_QUERY_THROW );
+
+ Reference< XPropertySet > xFormProperties( xController->getModel(), UNO_QUERY_THROW );
+ ::rtl::OUString aName;
+ OSL_VERIFY( xFormProperties->getPropertyValue( FM_PROP_NAME ) >>= aName );
+
+ // Insert a new item for the form
+ FmFormItem* pFormItem = new FmFormItem( m_xORB, pParent, xController, aName );
+ Insert( pParent->GetChildren().end(), pFormItem );
+
+ Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
+
+ // insert the existing filters for the form
+ String aTitle( SVX_RES( RID_STR_FILTER_FILTER_FOR ) );
+
+ Sequence< Sequence< ::rtl::OUString > > aExpressions = xFilterController->getPredicateExpressions();
+ for ( const Sequence< ::rtl::OUString >* pConjunctionTerm = aExpressions.getConstArray();
+ pConjunctionTerm != aExpressions.getConstArray() + aExpressions.getLength();
+ ++pConjunctionTerm
+ )
+ {
+ // we always display one row, even if there's no term to be displayed
+ FmFilterItems* pFilterItems = new FmFilterItems( m_xORB, pFormItem, aTitle );
+ Insert( pFormItem->GetChildren().end(), pFilterItems );
+
+ const Sequence< ::rtl::OUString >& rDisjunction( *pConjunctionTerm );
+ for ( const ::rtl::OUString* pDisjunctiveTerm = rDisjunction.getConstArray();
+ pDisjunctiveTerm != rDisjunction.getConstArray() + rDisjunction.getLength();
+ ++pDisjunctiveTerm
+ )
+ {
+ if ( pDisjunctiveTerm->getLength() == 0 )
+ // no condition for this particular component in this particular conjunction term
+ continue;
+
+ const sal_Int32 nComponentIndex = pDisjunctiveTerm - rDisjunction.getConstArray();
+
+ // determine the display name of the control
+ const Reference< XControl > xFilterControl( xFilterController->getFilterComponent( nComponentIndex ) );
+ const ::rtl::OUString sDisplayName( lcl_getLabelName_nothrow( xFilterControl ) );
+
+ // insert a new entry
+ FmFilterItem* pANDCondition = new FmFilterItem( m_xORB, pFilterItems, sDisplayName, *pDisjunctiveTerm, nComponentIndex );
+ Insert( pFilterItems->GetChildren().end(), pANDCondition );
+ }
+
+ // title for the next conditions
+ aTitle = SVX_RES( RID_STR_FILTER_FILTER_OR );
+ }
+
+ // now add dependent controllers
+ Reference< XIndexAccess > xControllerAsIndex( xController, UNO_QUERY );
+ Update( xControllerAsIndex, pFormItem );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------
+FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XFormController > & xController) const
+{
+ for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
+ i != rItems.end(); i++)
+ {
+ FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
+ if (pForm)
+ {
+ if ( xController == pForm->GetController() )
+ return pForm;
+ else
+ {
+ pForm = Find(pForm->GetChildren(), xController);
+ if (pForm)
+ return pForm;
+ }
+ }
+ }
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XForm >& xForm) const
+{
+ for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
+ i != rItems.end(); i++)
+ {
+ FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
+ if (pForm)
+ {
+ if (xForm == pForm->GetController()->getModel())
+ return pForm;
+ else
+ {
+ pForm = Find(pForm->GetChildren(), xForm);
+ if (pForm)
+ return pForm;
+ }
+ }
+ }
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::SetCurrentController(const Reference< XFormController > & xCurrent)
+{
+ if ( xCurrent == m_xController )
+ return;
+
+ m_xController = xCurrent;
+
+ FmFormItem* pItem = Find( m_aChildren, xCurrent );
+ if ( !pItem )
+ return;
+
+ try
+ {
+ Reference< XFilterController > xFilterController( m_xController, UNO_QUERY_THROW );
+ const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
+ if ( pItem->GetChildren().size() > (size_t)nActiveTerm )
+ {
+ SetCurrentItems( static_cast< FmFilterItems* >( pItem->GetChildren()[ nActiveTerm ] ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::AppendFilterItems( FmFormItem& _rFormItem )
+{
+ // insert the condition behind the last filter items
+ ::std::vector<FmFilterData*>::reverse_iterator iter;
+ for ( iter = _rFormItem.GetChildren().rbegin();
+ iter != _rFormItem.GetChildren().rend();
+ ++iter
+ )
+ {
+ if ((*iter)->ISA(FmFilterItems))
+ break;
+ }
+
+ sal_Int32 nInsertPos = iter.base() - _rFormItem.GetChildren().begin();
+ // delegate this to the FilterController, it will notify us, which will let us update our model
+ try
+ {
+ Reference< XFilterController > xFilterController( _rFormItem.GetFilterController(), UNO_SET_THROW );
+ if ( nInsertPos >= xFilterController->getDisjunctiveTerms() )
+ xFilterController->appendEmptyDisjunctiveTerm();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Insert(const ::std::vector<FmFilterData*>::iterator& rPos, FmFilterData* pData)
+{
+ ::std::vector<FmFilterData*>& rItems = pData->GetParent()->GetChildren();
+ sal_Int32 nPos = rPos == rItems.end() ? LIST_APPEND : rPos - rItems.begin();
+ rItems.insert(rPos, pData);
+
+ // UI benachrichtigen
+ FmFilterInsertedHint aInsertedHint(pData, nPos);
+ Broadcast( aInsertedHint );
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Remove(FmFilterData* pData)
+{
+ FmParentData* pParent = pData->GetParent();
+ ::std::vector<FmFilterData*>& rItems = pParent->GetChildren();
+
+ // erase the item from the model
+ ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pData);
+ DBG_ASSERT(i != rItems.end(), "FmFilterModel::Remove(): unknown Item");
+ // position within the parent
+ sal_Int32 nPos = i - rItems.begin();
+ if (pData->ISA(FmFilterItems))
+ {
+ FmFormItem* pFormItem = (FmFormItem*)pParent;
+
+ try
+ {
+ Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
+
+ bool bEmptyLastTerm = ( ( nPos == 0 ) && xFilterController->getDisjunctiveTerms() == 1 );
+ if ( bEmptyLastTerm )
+ {
+ // remove all children (by setting an empty predicate expression)
+ ::std::vector< FmFilterData* >& rChildren = ((FmFilterItems*)pData)->GetChildren();
+ while ( !rChildren.empty() )
+ {
+ ::std::vector< FmFilterData* >::iterator removePos = rChildren.end() - 1;
+ FmFilterItem* pFilterItem = PTR_CAST( FmFilterItem, *removePos );
+ m_pAdapter->setText( nPos, pFilterItem, ::rtl::OUString() );
+ Remove( removePos );
+ }
+ }
+ else
+ {
+ xFilterController->removeDisjunctiveTerm( nPos );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ else // FormItems can not be deleted
+ {
+ FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, pData);
+
+ // if its the last condition remove the parent
+ if (rItems.size() == 1)
+ Remove(pFilterItem->GetParent());
+ else
+ {
+ // find the position of the father within his father
+ ::std::vector<FmFilterData*>& rParentParentItems = pData->GetParent()->GetParent()->GetChildren();
+ ::std::vector<FmFilterData*>::iterator j = ::std::find(rParentParentItems.begin(), rParentParentItems.end(), pFilterItem->GetParent());
+ DBG_ASSERT(j != rParentParentItems.end(), "FmFilterModel::Remove(): unknown Item");
+ sal_Int32 nParentPos = j - rParentParentItems.begin();
+
+ // EmptyText removes the filter
+ m_pAdapter->setText(nParentPos, pFilterItem, ::rtl::OUString());
+ Remove( i );
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Remove( const ::std::vector<FmFilterData*>::iterator& rPos )
+{
+ // remove from parent's child list
+ FmFilterData* pData = *rPos;
+ pData->GetParent()->GetChildren().erase( rPos );
+
+ // notify the view, this will remove the actual SvLBoxEntry
+ FmFilterRemovedHint aRemoveHint( pData );
+ Broadcast( aRemoveHint );
+
+ delete pData;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFilterModel::ValidateText(FmFilterItem* pItem, UniString& rText, UniString& rErrorMsg) const
+{
+ FmFormItem* pFormItem = PTR_CAST( FmFormItem, pItem->GetParent()->GetParent() );
+ try
+ {
+ Reference< XFormController > xFormController( pFormItem->GetController() );
+ // obtain the connection of the form belonging to the controller
+ OStaticDataAccessTools aStaticTools;
+ Reference< XRowSet > xRowSet( xFormController->getModel(), UNO_QUERY_THROW );
+ Reference< XConnection > xConnection( aStaticTools.getRowSetConnection( xRowSet ) );
+
+ // obtain a number formatter for this connection
+ // TODO: shouldn't this be cached?
+ Reference< XNumberFormatsSupplier > xFormatSupplier = aStaticTools.getNumberFormats( xConnection, sal_True );
+ Reference< XNumberFormatter > xFormatter( m_xORB->createInstance( FM_NUMBER_FORMATTER ), UNO_QUERY );
+ xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
+
+ // get the field (database column) which the item is responsible for
+ Reference< XFilterController > xFilterController( xFormController, UNO_QUERY_THROW );
+ Reference< XPropertySet > xField( lcl_getBoundField_nothrow( xFilterController->getFilterComponent( pItem->GetComponentIndex() ) ), UNO_SET_THROW );
+
+ // parse the given text as filter predicate
+ ::rtl::OUString aErr, aTxt( rText );
+ ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree( aErr, aTxt, xFormatter, xField );
+ rErrorMsg = aErr;
+ rText = aTxt;
+ if ( xParseNode.is() )
+ {
+ ::rtl::OUString aPreparedText;
+ Locale aAppLocale = Application::GetSettings().GetUILocale();
+ xParseNode->parseNodeToPredicateStr(
+ aPreparedText, xConnection, xFormatter, xField, aAppLocale, '.', getParseContext() );
+ rText = aPreparedText;
+ return sal_True;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::Append(FmFilterItems* pItems, FmFilterItem* pFilterItem)
+{
+ Insert(pItems->GetChildren().end(), pFilterItem);
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::SetTextForItem(FmFilterItem* pItem, const ::rtl::OUString& rText)
+{
+ ::std::vector<FmFilterData*>& rItems = pItem->GetParent()->GetParent()->GetChildren();
+ ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pItem->GetParent());
+ sal_Int32 nParentPos = i - rItems.begin();
+
+ m_pAdapter->setText(nParentPos, pItem, rText);
+
+ if (!rText)
+ Remove(pItem);
+ else
+ {
+ // Change the text
+ pItem->SetText(rText);
+ FmFilterTextChangedHint aChangeHint(pItem);
+ Broadcast( aChangeHint );
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::SetCurrentItems(FmFilterItems* pCurrent)
+{
+ if (m_pCurrentItems == pCurrent)
+ return;
+
+ // search for the condition
+ if (pCurrent)
+ {
+ FmFormItem* pFormItem = (FmFormItem*)pCurrent->GetParent();
+ ::std::vector<FmFilterData*>& rItems = pFormItem->GetChildren();
+ ::std::vector<FmFilterData*>::const_iterator i = ::std::find(rItems.begin(), rItems.end(), pCurrent);
+
+ if (i != rItems.end())
+ {
+ // determine the filter position
+ sal_Int32 nPos = i - rItems.begin();
+ try
+ {
+ Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
+ xFilterController->setActiveTerm( nPos );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ if ( m_xController != pFormItem->GetController() )
+ // calls SetCurrentItems again
+ SetCurrentController( pFormItem->GetController() );
+ else
+ m_pCurrentItems = pCurrent;
+ }
+ else
+ m_pCurrentItems = NULL;
+ }
+ else
+ m_pCurrentItems = NULL;
+
+
+ // UI benachrichtigen
+ FmFilterCurrentChangedHint aHint;
+ Broadcast( aHint );
+}
+
+//------------------------------------------------------------------------
+void FmFilterModel::EnsureEmptyFilterRows( FmParentData& _rItem )
+{
+ // checks whether for each form there's one free level for input
+ ::std::vector< FmFilterData* >& rChildren = _rItem.GetChildren();
+ sal_Bool bAppendLevel = _rItem.ISA( FmFormItem );
+
+ for ( ::std::vector<FmFilterData*>::iterator i = rChildren.begin();
+ i != rChildren.end();
+ ++i
+ )
+ {
+ FmFilterItems* pItems = PTR_CAST(FmFilterItems, *i);
+ if ( pItems && pItems->GetChildren().empty() )
+ {
+ bAppendLevel = sal_False;
+ break;
+ }
+
+ FmFormItem* pFormItem = PTR_CAST(FmFormItem, *i);
+ if (pFormItem)
+ {
+ EnsureEmptyFilterRows( *pFormItem );
+ continue;
+ }
+ }
+
+ if ( bAppendLevel )
+ {
+ FmFormItem* pFormItem = PTR_CAST( FmFormItem, &_rItem );
+ OSL_ENSURE( pFormItem, "FmFilterModel::EnsureEmptyFilterRows: no FmFormItem, but a FmFilterItems child?" );
+ if ( pFormItem )
+ AppendFilterItems( *pFormItem );
+ }
+}
+
+//========================================================================
+// class FmFilterItemsString
+//========================================================================
+class FmFilterItemsString : public SvLBoxString
+{
+public:
+ FmFilterItemsString( SvLBoxEntry* pEntry, sal_uInt16 nFlags, const XubString& rStr )
+ :SvLBoxString(pEntry,nFlags,rStr){}
+
+ virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry);
+ virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData);
+};
+
+const int nxDBmp = 12;
+//------------------------------------------------------------------------
+void FmFilterItemsString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* pEntry )
+{
+ FmFilterItems* pRow = (FmFilterItems*)pEntry->GetUserData();
+ FmFormItem* pForm = (FmFormItem*)pRow->GetParent();
+
+ // current filter is significant painted
+ const bool bIsCurrentFilter = pForm->GetChildren()[ pForm->GetFilterController()->getActiveTerm() ] == pRow;
+ if ( bIsCurrentFilter )
+ {
+ rDev.Push( PUSH_LINECOLOR );
+
+ rDev.SetLineColor( rDev.GetTextColor() );
+
+ Rectangle aRect( rPos, GetSize( &rDev, pEntry ) );
+ Point aFirst( rPos.X(), aRect.Bottom() - 6 );
+ Point aSecond(aFirst .X() + 2, aFirst.Y() + 3 );
+
+ rDev.DrawLine( aFirst, aSecond );
+
+ aFirst = aSecond;
+ aFirst.X() += 1;
+ aSecond.X() += 6;
+ aSecond.Y() -= 5;
+
+ rDev.DrawLine( aFirst, aSecond );
+
+ rDev.Pop();
+ }
+
+ rDev.DrawText( Point(rPos.X() + nxDBmp, rPos.Y()), GetText() );
+}
+
+//------------------------------------------------------------------------
+void FmFilterItemsString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
+{
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+
+ Size aSize(pView->GetTextWidth(GetText()), pView->GetTextHeight());
+ aSize.Width() += nxDBmp;
+ pViewData->aSize = aSize;
+}
+
+//========================================================================
+// class FmFilterString
+//========================================================================
+class FmFilterString : public SvLBoxString
+{
+ UniString m_aName;
+
+public:
+ FmFilterString( SvLBoxEntry* pEntry, sal_uInt16 nFlags, const XubString& rStr, const UniString& aName)
+ :SvLBoxString(pEntry,nFlags,rStr)
+ ,m_aName(aName)
+ {
+ m_aName.AppendAscii(": ");
+ }
+
+ virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry);
+ virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData);
+};
+
+const int nxD = 4;
+
+//------------------------------------------------------------------------
+void FmFilterString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
+{
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+
+ Font aOldFont( pView->GetFont());
+ Font aFont( aOldFont );
+ aFont.SetWeight(WEIGHT_BOLD);
+ pView->SetFont( aFont );
+
+ Size aSize(pView->GetTextWidth(m_aName), pView->GetTextHeight());
+ pView->SetFont( aOldFont );
+ aSize.Width() += pView->GetTextWidth(GetText()) + nxD;
+ pViewData->aSize = aSize;
+}
+
+//------------------------------------------------------------------------
+void FmFilterString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* /*pEntry*/ )
+{
+ Font aOldFont( rDev.GetFont());
+ Font aFont( aOldFont );
+ aFont.SetWeight(WEIGHT_BOLD);
+ rDev.SetFont( aFont );
+
+ Point aPos(rPos);
+ rDev.DrawText( aPos, m_aName );
+
+ // position for the second text
+ aPos.X() += rDev.GetTextWidth(m_aName) + nxD;
+ rDev.SetFont( aOldFont );
+ rDev.DrawText( aPos, GetText() );
+}
+
+//========================================================================
+// class FmFilterNavigator
+//========================================================================
+FmFilterNavigator::FmFilterNavigator( Window* pParent )
+ :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HASBUTTONSATROOT )
+ ,m_pModel( NULL )
+ ,m_pEditingCurrently( NULL )
+ ,m_aControlExchange( this )
+ ,m_aTimerCounter( 0 )
+ ,m_aDropActionType( DA_SCROLLUP )
+{
+ SetHelpId( HID_FILTER_NAVIGATOR );
+
+ {
+ ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
+ SetNodeBitmaps(
+ aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
+ aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
+ );
+ }
+
+ m_pModel = new FmFilterModel(comphelper::getProcessServiceFactory());
+ StartListening( *m_pModel );
+
+ EnableInplaceEditing( sal_True );
+ SetSelectionMode(MULTIPLE_SELECTION);
+
+ SetDragDropMode(0xFFFF);
+
+ m_aDropActionTimer.SetTimeoutHdl(LINK(this, FmFilterNavigator, OnDropActionTimer));
+}
+
+//------------------------------------------------------------------------
+FmFilterNavigator::~FmFilterNavigator()
+{
+ EndListening( *m_pModel );
+ delete m_pModel;
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::Clear()
+{
+ m_pModel->Clear();
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::UpdateContent(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
+{
+ if (xCurrent == m_pModel->GetCurrentController())
+ return;
+
+ m_pModel->Update(xControllers, xCurrent);
+
+ // expand the filters for the current controller
+ SvLBoxEntry* pEntry = FindEntry(m_pModel->GetCurrentForm());
+ if (pEntry && !IsExpanded(pEntry))
+ {
+ SelectAll(sal_False);
+
+ if (!IsExpanded(pEntry))
+ Expand(pEntry);
+
+ pEntry = FindEntry(m_pModel->GetCurrentItems());
+ if (pEntry)
+ {
+ if (!IsExpanded(pEntry))
+ Expand(pEntry);
+ Select(pEntry, sal_True);
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFilterNavigator::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection )
+{
+ m_pEditingCurrently = pEntry;
+ if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
+ return sal_False;
+
+ return pEntry && ((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem);
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFilterNavigator::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText )
+{
+ DBG_ASSERT(pEntry == m_pEditingCurrently, "FmFilterNavigator::EditedEntry: suspicious entry!");
+ m_pEditingCurrently = NULL;
+
+ if (EditingCanceled())
+ return sal_True;
+
+ DBG_ASSERT(((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem),
+ "FmFilterNavigator::EditedEntry() wrong entry");
+
+ UniString aText(rNewText);
+ aText.EraseTrailingChars();
+ aText.EraseLeadingChars();
+ if (aText.Len() == 0)
+ {
+ // deleting the entry asynchron
+ ULONG nEvent;
+ PostUserEvent(nEvent, LINK(this, FmFilterNavigator, OnRemove), pEntry);
+ }
+ else
+ {
+ UniString aErrorMsg;
+
+ if (m_pModel->ValidateText((FmFilterItem*)pEntry->GetUserData(), aText, aErrorMsg))
+ {
+ GrabFocus();
+ // this will set the text at the FmFilterItem, as well as update any filter controls
+ // which are connected to this particular entry
+ m_pModel->SetTextForItem( static_cast< FmFilterItem* >( pEntry->GetUserData() ), aText );
+
+ SetCursor( pEntry, sal_True );
+ SetEntryText( pEntry, aText );
+ }
+ else
+ {
+ // display the error and return sal_False
+ SQLContext aError;
+ aError.Message = String(SVX_RES(RID_STR_SYNTAXERROR));
+ aError.Details = aErrorMsg;
+ displayException(aError, this);
+
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmFilterNavigator, OnRemove, SvLBoxEntry*, pEntry )
+{
+ // now remove the entry
+ m_pModel->Remove((FmFilterData*) pEntry->GetUserData());
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmFilterNavigator, OnDropActionTimer, void*, EMPTYARG )
+{
+ if (--m_aTimerCounter > 0)
+ return 0L;
+
+ switch (m_aDropActionType)
+ {
+ case DA_SCROLLUP :
+ ScrollOutputArea(1);
+ m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
+ break;
+ case DA_SCROLLDOWN :
+ ScrollOutputArea(-1);
+ m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
+ break;
+ case DA_EXPANDNODE:
+ {
+ SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered);
+ if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
+ // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich
+ // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ...
+ // aber ich denke, die BK sollte es auch so vertragen
+ Expand(pToExpand);
+
+ // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun
+ m_aDropActionTimer.Stop();
+ }
+ break;
+ }
+ return 0L;
+}
+
+
+//------------------------------------------------------------------------
+sal_Int8 FmFilterNavigator::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ Point aDropPos = rEvt.maPosPixel;
+
+ // kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen)
+ if (rEvt.mbLeaving)
+ {
+ if (m_aDropActionTimer.IsActive())
+ m_aDropActionTimer.Stop();
+ }
+ else
+ {
+ sal_Bool bNeedTrigger = sal_False;
+ // auf dem ersten Eintrag ?
+ if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
+ {
+ m_aDropActionType = DA_SCROLLUP;
+ bNeedTrigger = sal_True;
+ }
+ else
+ {
+ // auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig
+ // abschliessen wuerde) ?
+ if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
+ {
+ m_aDropActionType = DA_SCROLLDOWN;
+ bNeedTrigger = sal_True;
+ }
+ else
+ { // is it an entry whith children, and not yet expanded?
+ SvLBoxEntry* pDropppedOn = GetEntry(aDropPos);
+ if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
+ {
+ // -> aufklappen
+ m_aDropActionType = DA_EXPANDNODE;
+ bNeedTrigger = sal_True;
+ }
+ }
+ }
+ if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
+ {
+ // neu anfangen zu zaehlen
+ m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
+ // die Pos merken, da ich auch QueryDrops bekomme, wenn sich die Maus gar nicht bewegt hat
+ m_aTimerTriggered = aDropPos;
+ // und den Timer los
+ if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
+ {
+ m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
+ m_aDropActionTimer.Start();
+ }
+ }
+ else if (!bNeedTrigger)
+ m_aDropActionTimer.Stop();
+ }
+
+
+ // Hat das Object das richtige Format?
+ if (!m_aControlExchange.isDragSource())
+ return DND_ACTION_NONE;
+
+ if (!m_aControlExchange->hasFormat(GetDataFlavorExVector()))
+ return DND_ACTION_NONE;
+
+ // do we conain the formitem?
+ if (!FindEntry(m_aControlExchange->getFormItem()))
+ return DND_ACTION_NONE;
+
+ SvLBoxEntry* pDropTarget = GetEntry(aDropPos);
+ if (!pDropTarget)
+ return DND_ACTION_NONE;
+
+ FmFilterData* pData = (FmFilterData*)pDropTarget->GetUserData();
+ FmFormItem* pForm = NULL;
+ if (pData->ISA(FmFilterItem))
+ {
+ pForm = PTR_CAST(FmFormItem,pData->GetParent()->GetParent());
+ if (pForm != m_aControlExchange->getFormItem())
+ return DND_ACTION_NONE;
+ }
+ else if (pData->ISA(FmFilterItems))
+ {
+ pForm = PTR_CAST(FmFormItem,pData->GetParent());
+ if (pForm != m_aControlExchange->getFormItem())
+ return DND_ACTION_NONE;
+ }
+ else
+ return DND_ACTION_NONE;
+
+ return rEvt.mnAction;
+}
+// -----------------------------------------------------------------------------
+namespace
+{
+ FmFilterItems* getTargetItems(SvLBoxEntry* _pTarget)
+ {
+ FmFilterData* pData = static_cast<FmFilterData*>(_pTarget->GetUserData());
+ FmFilterItems* pTargetItems = pData->ISA(FmFilterItems)
+ ?
+ PTR_CAST(FmFilterItems,pData)
+ :
+ PTR_CAST(FmFilterItems,pData->GetParent());
+ return pTargetItems;
+ }
+}
+//------------------------------------------------------------------------
+sal_Int8 FmFilterNavigator::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ // ware schlecht, wenn nach dem Droppen noch gescrollt wird ...
+ if (m_aDropActionTimer.IsActive())
+ m_aDropActionTimer.Stop();
+
+ // Format-Ueberpruefung
+ if (!m_aControlExchange.isDragSource())
+ return DND_ACTION_NONE;
+
+ // das Ziel des Drop sowie einige Daten darueber
+ Point aDropPos = rEvt.maPosPixel;
+ SvLBoxEntry* pDropTarget = GetEntry( aDropPos );
+ if (!pDropTarget)
+ return DND_ACTION_NONE;
+
+ // search the container where to add the items
+ FmFilterItems* pTargetItems = getTargetItems(pDropTarget);
+ SelectAll(sal_False);
+ SvLBoxEntry* pEntry = FindEntry(pTargetItems);
+ Select(pEntry, sal_True);
+ SetCurEntry(pEntry);
+
+ insertFilterItem(m_aControlExchange->getDraggedEntries(),pTargetItems,DND_ACTION_COPY == rEvt.mnAction);
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::InitEntry(SvLBoxEntry* pEntry,
+ const XubString& rStr,
+ const Image& rImg1,
+ const Image& rImg2,
+ SvLBoxButtonKind eButtonKind)
+{
+ SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind );
+ SvLBoxString* pString = NULL;
+
+ if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
+ pString = new FmFilterString(pEntry, 0, rStr, ((FmFilterItem*)pEntry->GetUserData())->GetFieldName());
+ else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
+ pString = new FmFilterItemsString(pEntry, 0, rStr );
+
+ if (pString)
+ pEntry->ReplaceItem( pString, 1 );
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFilterNavigator::Select( SvLBoxEntry* pEntry, sal_Bool bSelect )
+{
+ if (bSelect == IsSelected(pEntry)) // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;)
+ return sal_True;
+
+ if (SvTreeListBox::Select(pEntry, bSelect))
+ {
+ if (bSelect)
+ {
+ FmFormItem* pFormItem = NULL;
+ if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
+ pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent();
+ else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
+ pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent();
+ else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem))
+ pFormItem = (FmFormItem*)pEntry->GetUserData();
+
+ if (pFormItem)
+ {
+ // will the controller be exchanged?
+ if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
+ m_pModel->SetCurrentItems((FmFilterItems*)((FmFilterItem*)pEntry->GetUserData())->GetParent());
+ else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
+ m_pModel->SetCurrentItems((FmFilterItems*)pEntry->GetUserData());
+ else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem))
+ m_pModel->SetCurrentController(((FmFormItem*)pEntry->GetUserData())->GetController());
+ }
+ }
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ if (rHint.ISA(FmFilterInsertedHint))
+ {
+ FmFilterInsertedHint* pHint = (FmFilterInsertedHint*)&rHint;
+ Insert(pHint->GetData(), pHint->GetPos());
+ }
+ else if( rHint.ISA(FilterClearingHint) )
+ {
+ SvTreeListBox::Clear();
+ }
+ else if( rHint.ISA(FmFilterRemovedHint) )
+ {
+ FmFilterRemovedHint* pHint = (FmFilterRemovedHint*)&rHint;
+ Remove(pHint->GetData());
+ }
+ else if( rHint.ISA(FmFilterTextChangedHint) )
+ {
+ FmFilterTextChangedHint* pHint = (FmFilterTextChangedHint*)&rHint;
+ SvLBoxEntry* pEntry = FindEntry(pHint->GetData());
+ if (pEntry)
+ SetEntryText( pEntry, pHint->GetData()->GetText());
+ }
+ else if( rHint.ISA(FmFilterCurrentChangedHint) )
+ {
+ // invalidate the entries
+ for (SvLBoxEntry* pEntry = First(); pEntry != NULL;
+ pEntry = Next(pEntry))
+ GetModel()->InvalidateEntry( pEntry );
+ }
+}
+
+//------------------------------------------------------------------------
+SvLBoxEntry* FmFilterNavigator::FindEntry(const FmFilterData* pItem) const
+{
+ SvLBoxEntry* pEntry = NULL;
+ if (pItem)
+ {
+ for (pEntry = First(); pEntry != NULL; pEntry = Next( pEntry ))
+ {
+ FmFilterData* pEntryItem = (FmFilterData*)pEntry->GetUserData();
+ if (pEntryItem == pItem)
+ break;
+ }
+ }
+ return pEntry;
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::Insert(FmFilterData* pItem, sal_Int32 nPos)
+{
+ const FmParentData* pParent = pItem->GetParent() ? pItem->GetParent() : GetFilterModel();
+
+ // insert the item
+ SvLBoxEntry* pParentEntry = FindEntry( pParent );
+ InsertEntry( pItem->GetText(), pItem->GetImage(), pItem->GetImage(), pParentEntry, sal_False, nPos, pItem );
+ if ( pParentEntry )
+ Expand( pParentEntry );
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigator::Remove(FmFilterData* pItem)
+{
+ // der Entry zu den Daten
+ SvLBoxEntry* pEntry = FindEntry(pItem);
+
+ if (pEntry == m_pEditingCurrently)
+ // cancel editing
+ EndEditing(sal_True);
+
+ if (pEntry)
+ GetModel()->Remove( pEntry );
+}
+// -----------------------------------------------------------------------------
+FmFormItem* FmFilterNavigator::getSelectedFilterItems(::std::vector<FmFilterItem*>& _rItemList)
+{
+ // be sure that the data is only used within only one form!
+ FmFormItem* pFirstItem = NULL;
+
+ sal_Bool bHandled = sal_True;
+ sal_Bool bFoundSomething = sal_False;
+ for (SvLBoxEntry* pEntry = FirstSelected();
+ bHandled && pEntry != NULL;
+ pEntry = NextSelected(pEntry))
+ {
+ FmFilterItem* pFilter = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData());
+ if (pFilter)
+ {
+ FmFormItem* pForm = PTR_CAST(FmFormItem,pFilter->GetParent()->GetParent());
+ if (!pForm)
+ bHandled = sal_False;
+ else if (!pFirstItem)
+ pFirstItem = pForm;
+ else if (pFirstItem != pForm)
+ bHandled = sal_False;
+
+ if (bHandled)
+ {
+ _rItemList.push_back(pFilter);
+ bFoundSomething = sal_True;
+ }
+ }
+ }
+ if ( !bHandled || !bFoundSomething )
+ pFirstItem = NULL;
+ return pFirstItem;
+}
+// -----------------------------------------------------------------------------
+void FmFilterNavigator::insertFilterItem(const ::std::vector<FmFilterItem*>& _rFilterList,FmFilterItems* _pTargetItems,sal_Bool _bCopy)
+{
+ ::std::vector<FmFilterItem*>::const_iterator aEnd = _rFilterList.end();
+ for ( ::std::vector< FmFilterItem* >::const_iterator i = _rFilterList.begin();
+ i != aEnd;
+ ++i
+ )
+ {
+ FmFilterItem* pLookupItem( *i );
+ if ( pLookupItem->GetParent() == _pTargetItems )
+ continue;
+
+ FmFilterItem* pFilterItem = _pTargetItems->Find( pLookupItem->GetComponentIndex() );
+ String aText = pLookupItem->GetText();
+ if ( !pFilterItem )
+ {
+ pFilterItem = new FmFilterItem( m_pModel->getORB(), _pTargetItems, pLookupItem->GetFieldName(), aText, pLookupItem->GetComponentIndex() );
+ m_pModel->Append( _pTargetItems, pFilterItem );
+ }
+
+ if ( !_bCopy )
+ m_pModel->Remove( pLookupItem );
+
+ // now set the text for the new dragged item
+ m_pModel->SetTextForItem( pFilterItem, aText );
+ }
+
+ m_pModel->EnsureEmptyFilterRows( *_pTargetItems->GetParent() );
+}
+
+//------------------------------------------------------------------------------
+void FmFilterNavigator::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
+{
+ EndSelection();
+
+ // be sure that the data is only used within a only one form!
+ m_aControlExchange.prepareDrag();
+
+ ::std::vector<FmFilterItem*> aItemList;
+ if ( FmFormItem* pFirstItem = getSelectedFilterItems(aItemList) )
+ {
+ m_aControlExchange->setDraggedEntries(aItemList);
+ m_aControlExchange->setFormItem(pFirstItem);
+ m_aControlExchange.startDrag( DND_ACTION_COPYMOVE );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmFilterNavigator::Command( const CommandEvent& rEvt )
+{
+ sal_Bool bHandled = sal_False;
+ switch (rEvt.GetCommand())
+ {
+ case COMMAND_CONTEXTMENU:
+ {
+ // die Stelle, an der geklickt wurde
+ Point aWhere;
+ SvLBoxEntry* pClicked = NULL;
+ if (rEvt.IsMouseEvent())
+ {
+ aWhere = rEvt.GetMousePosPixel();
+ pClicked = GetEntry(aWhere);
+ if (pClicked == NULL)
+ break;
+
+ if (!IsSelected(pClicked))
+ {
+ SelectAll(sal_False);
+ Select(pClicked, sal_True);
+ SetCurEntry(pClicked);
+ }
+ }
+ else
+ {
+ pClicked = GetCurEntry();
+ if (!pClicked)
+ break;
+ aWhere = GetEntryPosition( pClicked );
+ }
+
+ ::std::vector<FmFilterData*> aSelectList;
+ for (SvLBoxEntry* pEntry = FirstSelected();
+ pEntry != NULL;
+ pEntry = NextSelected(pEntry))
+ {
+ // don't delete forms
+ FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData());
+ if (!pForm)
+ aSelectList.push_back((FmFilterData*)pEntry->GetUserData());
+ }
+ if (aSelectList.size() == 1)
+ {
+ // don't delete the only empty row of a form
+ FmFilterItems* pFilterItems = PTR_CAST(FmFilterItems, aSelectList[0]);
+ if (pFilterItems && pFilterItems->GetChildren().empty()
+ && pFilterItems->GetParent()->GetChildren().size() == 1)
+ aSelectList.clear();
+ }
+
+ PopupMenu aContextMenu(SVX_RES(RID_FM_FILTER_MENU));
+
+ // every condition could be deleted except the first one if its the only one
+ aContextMenu.EnableItem( SID_FM_DELETE, !aSelectList.empty() );
+
+ //
+ sal_Bool bEdit = PTR_CAST(FmFilterItem, (FmFilterData*)pClicked->GetUserData()) != NULL &&
+ IsSelected(pClicked) && GetSelectionCount() == 1;
+
+ aContextMenu.EnableItem( SID_FM_FILTER_EDIT,
+ bEdit );
+ aContextMenu.EnableItem( SID_FM_FILTER_IS_NULL,
+ bEdit );
+ aContextMenu.EnableItem( SID_FM_FILTER_IS_NOT_NULL,
+ bEdit );
+
+ aContextMenu.RemoveDisabledEntries(sal_True, sal_True);
+ sal_uInt16 nSlotId = aContextMenu.Execute( this, aWhere );
+ switch( nSlotId )
+ {
+ case SID_FM_FILTER_EDIT:
+ {
+ EditEntry( pClicked );
+ } break;
+ case SID_FM_FILTER_IS_NULL:
+ case SID_FM_FILTER_IS_NOT_NULL:
+ {
+ UniString aErrorMsg;
+ UniString aText;
+ if (nSlotId == SID_FM_FILTER_IS_NULL)
+ aText.AssignAscii("IS NULL");
+ else
+ aText.AssignAscii("IS NOT NULL");
+
+ m_pModel->ValidateText((FmFilterItem*)pClicked->GetUserData(),
+ aText, aErrorMsg);
+ m_pModel->SetTextForItem((FmFilterItem*)pClicked->GetUserData(), aText);
+ } break;
+ case SID_FM_DELETE:
+ {
+ DeleteSelection();
+ } break;
+ }
+ bHandled = sal_True;
+ } break;
+ }
+
+ if (!bHandled)
+ SvTreeListBox::Command( rEvt );
+}
+// -----------------------------------------------------------------------------
+SvLBoxEntry* FmFilterNavigator::getNextEntry(SvLBoxEntry* _pStartWith)
+{
+ SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : LastSelected();
+ pEntry = Next(pEntry);
+ // we need the next filter entry
+ while( pEntry && GetChildCount( pEntry ) == 0 && pEntry != Last() )
+ pEntry = Next(pEntry);
+ return pEntry;
+}
+// -----------------------------------------------------------------------------
+SvLBoxEntry* FmFilterNavigator::getPrevEntry(SvLBoxEntry* _pStartWith)
+{
+ SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : FirstSelected();
+ pEntry = Prev(pEntry);
+ // check if the previous entry is a filter, if so get the next prev
+ if ( pEntry && GetChildCount( pEntry ) != 0 )
+ {
+ pEntry = Prev(pEntry);
+ // if the entry is still no leaf return
+ if ( pEntry && GetChildCount( pEntry ) != 0 )
+ pEntry = NULL;
+ }
+ return pEntry;
+}
+//------------------------------------------------------------------------
+void FmFilterNavigator::KeyInput(const KeyEvent& rKEvt)
+{
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+
+ switch ( rKeyCode.GetCode() )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ {
+ if ( !rKeyCode.IsMod1() || !rKeyCode.IsMod2() || rKeyCode.IsShift() )
+ break;
+
+ ::std::vector<FmFilterItem*> aItemList;
+ if ( !getSelectedFilterItems( aItemList ) )
+ break;
+
+ ::std::mem_fun1_t<SvLBoxEntry*,FmFilterNavigator,SvLBoxEntry*> getter = ::std::mem_fun(&FmFilterNavigator::getNextEntry);
+ if ( rKeyCode.GetCode() == KEY_UP )
+ getter = ::std::mem_fun(&FmFilterNavigator::getPrevEntry);
+
+ SvLBoxEntry* pTarget = getter( this, NULL );
+ if ( !pTarget )
+ break;
+
+ FmFilterItems* pTargetItems = getTargetItems( pTarget );
+ if ( !pTargetItems )
+ break;
+
+ ::std::vector<FmFilterItem*>::const_iterator aEnd = aItemList.end();
+ sal_Bool bNextTargetItem = sal_True;
+ while ( bNextTargetItem )
+ {
+ ::std::vector<FmFilterItem*>::const_iterator i = aItemList.begin();
+ for (; i != aEnd; ++i)
+ {
+ if ( (*i)->GetParent() == pTargetItems )
+ {
+ pTarget = getter(this,pTarget);
+ if ( !pTarget )
+ return;
+ pTargetItems = getTargetItems( pTarget );
+ break;
+ }
+ else
+ {
+ FmFilterItem* pFilterItem = pTargetItems->Find( (*i)->GetComponentIndex() );
+ // we found the text component so jump above
+ if ( pFilterItem )
+ {
+ pTarget = getter( this, pTarget );
+ if ( !pTarget )
+ return;
+
+ pTargetItems = getTargetItems( pTarget );
+ break;
+ }
+ }
+ }
+ bNextTargetItem = i != aEnd && pTargetItems;
+ }
+
+ if ( pTargetItems )
+ {
+ insertFilterItem( aItemList, pTargetItems );
+ return;
+ }
+ }
+ break;
+
+ case KEY_DELETE:
+ {
+ if ( rKeyCode.GetModifier() )
+ break;
+
+ if ( !IsSelected( First() ) || GetEntryCount() > 1 )
+ DeleteSelection();
+ return;
+ }
+ }
+
+ SvTreeListBox::KeyInput(rKEvt);
+}
+
+//------------------------------------------------------------------------------
+void FmFilterNavigator::DeleteSelection()
+{
+ // to avoid the deletion of an entry twice (e.g. deletion of a parent and afterward
+ // the deletion of it's child, i have to shrink the selecton list
+ ::std::vector<SvLBoxEntry*> aEntryList;
+ for (SvLBoxEntry* pEntry = FirstSelected();
+ pEntry != NULL;
+ pEntry = NextSelected(pEntry))
+ {
+ FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData());
+ if (pFilterItem && IsSelected(GetParent(pEntry)))
+ continue;
+
+ FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData());
+ if (!pForm)
+ aEntryList.push_back(pEntry);
+ }
+
+ // Remove the selection
+ SelectAll(FALSE);
+
+ for (::std::vector<SvLBoxEntry*>::reverse_iterator i = aEntryList.rbegin();
+ // link problems with operator ==
+ i.base() != aEntryList.rend().base(); i++)
+ {
+ m_pModel->Remove((FmFilterData*)(*i)->GetUserData());
+ }
+}
+// -----------------------------------------------------------------------------
+
+//========================================================================
+// class FmFilterNavigatorWin
+//========================================================================
+FmFilterNavigatorWin::FmFilterNavigatorWin( SfxBindings* _pBindings, SfxChildWindow* _pMgr,
+ Window* _pParent )
+ :SfxDockingWindow( _pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) )
+ ,SfxControllerItem( SID_FM_FILTER_NAVIGATOR_CONTROL, *_pBindings )
+{
+ SetHelpId( HID_FILTER_NAVIGATOR_WIN );
+
+ m_pNavigator = new FmFilterNavigator( this );
+ m_pNavigator->Show();
+ SetText( SVX_RES(RID_STR_FILTER_NAVIGATOR) );
+ SfxDockingWindow::SetFloatingSize( Size(200,200) );
+}
+
+//------------------------------------------------------------------------
+FmFilterNavigatorWin::~FmFilterNavigatorWin()
+{
+ delete m_pNavigator;
+}
+
+//-----------------------------------------------------------------------
+void FmFilterNavigatorWin::UpdateContent(FmFormShell* pFormShell)
+{
+ if (!pFormShell)
+ m_pNavigator->UpdateContent( NULL, NULL );
+ else
+ {
+ Reference< XFormController > xController(pFormShell->GetImpl()->getActiveInternalController());
+ Reference< XIndexAccess > xContainer;
+ if (xController.is())
+ {
+ Reference< XChild > xChild(xController, UNO_QUERY);
+ for (Reference< XInterface > xParent(xChild->getParent());
+ xParent.is();
+ xParent = xChild.is() ? xChild->getParent() : Reference< XInterface > ())
+ {
+ xContainer = Reference< XIndexAccess > (xParent, UNO_QUERY);
+ xChild = Reference< XChild > (xParent, UNO_QUERY);
+ }
+ }
+ m_pNavigator->UpdateContent(xContainer, xController);
+ }
+}
+
+//-----------------------------------------------------------------------
+void FmFilterNavigatorWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if( !pState || SID_FM_FILTER_NAVIGATOR_CONTROL != nSID )
+ return;
+
+ if( eState >= SFX_ITEM_AVAILABLE )
+ {
+ FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() );
+ UpdateContent( pShell );
+ }
+ else
+ UpdateContent( NULL );
+}
+
+//-----------------------------------------------------------------------
+sal_Bool FmFilterNavigatorWin::Close()
+{
+ if ( m_pNavigator && m_pNavigator->IsEditingActive() )
+ m_pNavigator->EndEditing();
+
+ if ( m_pNavigator && m_pNavigator->IsEditingActive() )
+ // the EndEditing was vetoed (perhaps of an syntax error or such)
+ return sal_False;
+
+ UpdateContent( NULL );
+ return SfxDockingWindow::Close();
+}
+
+//-----------------------------------------------------------------------
+void FmFilterNavigatorWin::FillInfo( SfxChildWinInfo& rInfo ) const
+{
+ SfxDockingWindow::FillInfo( rInfo );
+ rInfo.bVisible = sal_False;
+}
+
+//-----------------------------------------------------------------------
+Size FmFilterNavigatorWin::CalcDockingSize( SfxChildAlignment eAlign )
+{
+ if ( ( eAlign == SFX_ALIGN_TOP ) || ( eAlign == SFX_ALIGN_BOTTOM ) )
+ return Size();
+
+ return SfxDockingWindow::CalcDockingSize( eAlign );
+}
+
+//-----------------------------------------------------------------------
+SfxChildAlignment FmFilterNavigatorWin::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign )
+{
+ switch (eAlign)
+ {
+ case SFX_ALIGN_LEFT:
+ case SFX_ALIGN_RIGHT:
+ case SFX_ALIGN_NOALIGNMENT:
+ return (eAlign);
+ default:
+ break;
+ }
+
+ return (eActAlign);
+}
+
+//------------------------------------------------------------------------
+void FmFilterNavigatorWin::Resize()
+{
+ SfxDockingWindow::Resize();
+
+ Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT );
+ Size aLogExplSize = aLogOutputSize;
+ aLogExplSize.Width() -= 6;
+ aLogExplSize.Height() -= 6;
+
+ Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT );
+ Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT );
+
+ m_pNavigator->SetPosSizePixel( aExplPos, aExplSize );
+}
+// -----------------------------------------------------------------------------
+void FmFilterNavigatorWin::GetFocus()
+{
+ // oj #97405#
+ if ( m_pNavigator )
+ m_pNavigator->GrabFocus();
+}
+// -----------------------------------------------------------------------------
+
+
+//========================================================================
+// class FmFilterNavigatorWinMgr
+//========================================================================
+SFX_IMPL_DOCKINGWINDOW( FmFilterNavigatorWinMgr, SID_FM_FILTER_NAVIGATOR )
+
+//-----------------------------------------------------------------------
+FmFilterNavigatorWinMgr::FmFilterNavigatorWinMgr( Window *_pParent, sal_uInt16 _nId,
+ SfxBindings *_pBindings, SfxChildWinInfo* _pInfo )
+ :SfxChildWindow( _pParent, _nId )
+{
+ pWindow = new FmFilterNavigatorWin( _pBindings, this, _pParent );
+ eChildAlignment = SFX_ALIGN_NOALIGNMENT;
+ ((SfxDockingWindow*)pWindow)->Initialize( _pInfo );
+}
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/filtnav.src b/svx/source/form/filtnav.src
new file mode 100644
index 000000000000..82b74e84331c
--- /dev/null
+++ b/svx/source/form/filtnav.src
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svx/svxids.hrc>
+#include "fmresids.hrc"
+Menu RID_FM_FILTER_MENU
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = SID_FM_DELETE ;
+ HelpID = SID_FM_DELETE ;
+ Text [ en-US ] = "~Delete" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_FILTER_EDIT ;
+ HelpID = SID_FM_FILTER_EDIT ;
+ Text [ en-US ] = "~Edit" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_FILTER_IS_NULL ;
+ HelpID = SID_FM_FILTER_IS_NULL ;
+ Text [ en-US ] = "~Is Null" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_FILTER_IS_NOT_NULL ;
+ HelpID = SID_FM_FILTER_IS_NOT_NULL ;
+ Text [ en-US ] = "I~s not Null" ;
+ };
+ };
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svx/source/form/fmPropBrw.cxx b/svx/source/form/fmPropBrw.cxx
new file mode 100644
index 000000000000..b146ae16d537
--- /dev/null
+++ b/svx/source/form/fmPropBrw.cxx
@@ -0,0 +1,727 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+
+#include "fmhelp.hrc"
+#include "fmprop.hrc"
+#include "fmPropBrw.hxx"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "fmshimp.hxx"
+#include "fmpgeimp.hxx"
+
+#include "svx/dialmgr.hxx"
+#include "svx/fmpage.hxx"
+#include "svx/fmshell.hxx"
+#include "svx/sdrpagewindow.hxx"
+#include "svx/svdpagv.hxx"
+#include "svx/svxids.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/awt/XLayoutConstrains.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/inspection/ObjectInspector.hpp>
+#include <com/sun/star/inspection/ObjectInspectorModel.hpp>
+#include <com/sun/star/form/inspection/DefaultFormComponentInspectorModel.hpp>
+#include <com/sun/star/inspection/XObjectInspectorUI.hpp>
+#include <com/sun/star/inspection/DefaultHelpProvider.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <cppuhelper/component_context.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/childwin.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <toolkit/unohlp.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/shl.hxx>
+#include <unotools/confignode.hxx>
+#include <vcl/stdtext.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::inspection;
+using namespace ::com::sun::star::form::inspection;
+using ::com::sun::star::awt::XWindow;
+
+/*************************************************************************/
+//========================================================================
+//= FmPropBrwMgr
+//========================================================================
+//-----------------------------------------------------------------------
+SFX_IMPL_FLOATINGWINDOW(FmPropBrwMgr, SID_FM_SHOW_PROPERTIES)
+
+//-----------------------------------------------------------------------
+FmPropBrwMgr::FmPropBrwMgr( Window* _pParent, sal_uInt16 _nId,
+ SfxBindings* _pBindings, SfxChildWinInfo* _pInfo)
+ :SfxChildWindow(_pParent, _nId)
+{
+ pWindow = new FmPropBrw( ::comphelper::getProcessServiceFactory(), _pBindings, this, _pParent, _pInfo );
+ eChildAlignment = SFX_ALIGN_NOALIGNMENT;
+ ((SfxFloatingWindow*)pWindow)->Initialize( _pInfo );
+}
+
+//========================================================================
+//========================================================================
+const long STD_WIN_SIZE_X = 300;
+const long STD_WIN_SIZE_Y = 350;
+
+const long STD_MIN_SIZE_X = 250;
+const long STD_MIN_SIZE_Y = 250;
+
+const long STD_WIN_POS_X = 50;
+const long STD_WIN_POS_Y = 50;
+const long WIN_BORDER = 2;
+const long MIN_WIN_SIZE_X = 50;
+const long MIN_WIN_SIZE_Y = 50;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::svxform;
+
+::rtl::OUString GetUIHeadlineName(sal_Int16 nClassId, const Any& aUnoObj)
+{
+ sal_uInt16 nClassNameResourceId = 0;
+
+ switch ( nClassId )
+ {
+ case FormComponentType::TEXTFIELD:
+ {
+ Reference< XInterface > xIFace;
+ aUnoObj >>= xIFace;
+ nClassNameResourceId = RID_STR_PROPTITLE_EDIT;
+ if (xIFace.is())
+ { // we have a chance to check if it's a formatted field model
+ Reference< XServiceInfo > xInfo(xIFace, UNO_QUERY);
+ if (xInfo.is() && (xInfo->supportsService(FM_SUN_COMPONENT_FORMATTEDFIELD)))
+ nClassNameResourceId = RID_STR_PROPTITLE_FORMATTED;
+ else if (!xInfo.is())
+ {
+ // couldn't distinguish between formatted and edit with the service name, so try with the properties
+ Reference< XPropertySet > xProps(xIFace, UNO_QUERY);
+ if (xProps.is())
+ {
+ Reference< XPropertySetInfo > xPropsInfo = xProps->getPropertySetInfo();
+ if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER))
+ nClassNameResourceId = RID_STR_PROPTITLE_FORMATTED;
+ }
+ }
+ }
+ }
+ break;
+
+ case FormComponentType::COMMANDBUTTON:
+ nClassNameResourceId = RID_STR_PROPTITLE_PUSHBUTTON; break;
+ case FormComponentType::RADIOBUTTON:
+ nClassNameResourceId = RID_STR_PROPTITLE_RADIOBUTTON; break;
+ case FormComponentType::CHECKBOX:
+ nClassNameResourceId = RID_STR_PROPTITLE_CHECKBOX; break;
+ case FormComponentType::LISTBOX:
+ nClassNameResourceId = RID_STR_PROPTITLE_LISTBOX; break;
+ case FormComponentType::COMBOBOX:
+ nClassNameResourceId = RID_STR_PROPTITLE_COMBOBOX; break;
+ case FormComponentType::GROUPBOX:
+ nClassNameResourceId = RID_STR_PROPTITLE_GROUPBOX; break;
+ case FormComponentType::IMAGEBUTTON:
+ nClassNameResourceId = RID_STR_PROPTITLE_IMAGEBUTTON; break;
+ case FormComponentType::FIXEDTEXT:
+ nClassNameResourceId = RID_STR_PROPTITLE_FIXEDTEXT; break;
+ case FormComponentType::GRIDCONTROL:
+ nClassNameResourceId = RID_STR_PROPTITLE_DBGRID; break;
+ case FormComponentType::FILECONTROL:
+ nClassNameResourceId = RID_STR_PROPTITLE_FILECONTROL; break;
+ case FormComponentType::DATEFIELD:
+ nClassNameResourceId = RID_STR_PROPTITLE_DATEFIELD; break;
+ case FormComponentType::TIMEFIELD:
+ nClassNameResourceId = RID_STR_PROPTITLE_TIMEFIELD; break;
+ case FormComponentType::NUMERICFIELD:
+ nClassNameResourceId = RID_STR_PROPTITLE_NUMERICFIELD; break;
+ case FormComponentType::CURRENCYFIELD:
+ nClassNameResourceId = RID_STR_PROPTITLE_CURRENCYFIELD; break;
+ case FormComponentType::PATTERNFIELD:
+ nClassNameResourceId = RID_STR_PROPTITLE_PATTERNFIELD; break;
+ case FormComponentType::IMAGECONTROL:
+ nClassNameResourceId = RID_STR_PROPTITLE_IMAGECONTROL; break;
+ case FormComponentType::HIDDENCONTROL:
+ nClassNameResourceId = RID_STR_PROPTITLE_HIDDEN; break;
+ case FormComponentType::SCROLLBAR:
+ nClassNameResourceId = RID_STR_PROPTITLE_SCROLLBAR; break;
+ case FormComponentType::SPINBUTTON:
+ nClassNameResourceId = RID_STR_PROPTITLE_SPINBUTTON; break;
+ case FormComponentType::NAVIGATIONBAR:
+ nClassNameResourceId = RID_STR_PROPTITLE_NAVBAR; break;
+ case FormComponentType::CONTROL:
+ default:
+ nClassNameResourceId = RID_STR_CONTROL; break;
+ }
+
+ if ( !nClassNameResourceId )
+ return ::rtl::OUString();
+
+ return ::rtl::OUString( String( SVX_RES( nClassNameResourceId ) ) );
+}
+
+//========================================================================
+// class FmPropBrw
+//========================================================================
+DBG_NAME(FmPropBrw);
+//------------------------------------------------------------------------
+FmPropBrw::FmPropBrw( const Reference< XMultiServiceFactory >& _xORB, SfxBindings* _pBindings,
+ SfxChildWindow* _pMgr, Window* _pParent, const SfxChildWinInfo* _pInfo )
+ :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_3DLOOK|WB_ROLLABLE) )
+ ,SfxControllerItem(SID_FM_PROPERTY_CONTROL, *_pBindings)
+ ,m_bInitialStateChange(sal_True)
+ ,m_bInStateChange( false )
+ ,m_xORB(_xORB)
+{
+ DBG_CTOR(FmPropBrw,NULL);
+
+ ::Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y);
+ SetMinOutputSizePixel(::Size(STD_MIN_SIZE_X,STD_MIN_SIZE_Y));
+ SetOutputSizePixel(aPropWinSize);
+ SetUniqueId(UID_FORMPROPBROWSER_FRAME);
+
+ try
+ {
+ // create a frame wrapper for myself
+ m_xMeAsFrame = Reference< XFrame >(m_xORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Frame")) ), UNO_QUERY);
+ if (m_xMeAsFrame.is())
+ {
+ // create an intermediate window, which is to be the container window of the frame
+ // Do *not* use |this| as container window for the frame, this would result in undefined
+ // responsiblity for this window (as soon as we initialize a frame with a window, the frame
+ // is responsible for it's life time, but |this| is controlled by the belonging SfxChildWindow)
+ // #i34249# - 2004-09-27 - fs@openoffice.org
+ Window* pContainerWindow = new Window( this );
+ pContainerWindow->Show();
+ m_xFrameContainerWindow = VCLUnoHelper::GetInterface ( pContainerWindow );
+
+ m_xMeAsFrame->initialize( m_xFrameContainerWindow );
+ m_xMeAsFrame->setName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("form property browser")) );
+ if ( _pBindings->GetDispatcher() )
+ {
+ ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFramesSupplier >
+ xSupp ( _pBindings->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY );
+// if ( xSupp.is() )
+// xSupp->getFrames()->append( m_xMeAsFrame );
+ // Don't append frame to frame hierachy to prevent UI_DEACTIVATE messages
+ // #i31834# - 2004-07-27 - cd@openoffice.org
+ }
+ }
+ }
+ catch (Exception&)
+ {
+ DBG_ERROR("FmPropBrw::FmPropBrw: could not create/initialize my frame!");
+ m_xMeAsFrame.clear();
+ }
+
+ if (m_xMeAsFrame.is())
+ _pMgr->SetFrame( m_xMeAsFrame );
+
+
+ if ( m_xBrowserComponentWindow.is() )
+ m_xBrowserComponentWindow->setVisible( sal_True );
+
+ if ( _pInfo )
+ m_sLastActivePage = _pInfo->aExtraString;
+}
+
+//------------------------------------------------------------------------
+void FmPropBrw::Resize()
+{
+ SfxFloatingWindow::Resize();
+
+ if ( m_xFrameContainerWindow.is() )
+ {
+ try
+ {
+ ::Size aOutputSize( GetOutputSizePixel() );
+ m_xFrameContainerWindow->setPosSize( 0, 0, aOutputSize.Width(), aOutputSize.Height(), awt::PosSize::POSSIZE );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::Resize: caught an exception!" );
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+FmPropBrw::~FmPropBrw()
+{
+ if (m_xBrowserController.is())
+ implDetachController();
+ try
+ {
+ // remove our own properties from the component context. We cannot ensure that the component context
+ // is freed (there might be refcount problems :-\), so at least ensure the context itself
+ // does hold the objects anymore
+ Reference<XNameContainer> xName(m_xInspectorContext,uno::UNO_QUERY);
+ if ( xName.is() )
+ {
+ const ::rtl::OUString pProps[] = { ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContextDocument" ) )
+ , ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogParentWindow" ) )
+ , ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlContext" ) )
+ , ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlShapeAccess" ) ) };
+ for ( size_t i = 0; i < SAL_N_ELEMENTS(pProps); ++i )
+ xName->removeByName( pProps[i] );
+ }
+ }
+ catch (const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ DBG_DTOR(FmPropBrw,NULL);
+}
+
+//-----------------------------------------------------------------------
+::rtl::OUString FmPropBrw::getCurrentPage() const
+{
+ ::rtl::OUString sCurrentPage;
+ try
+ {
+ if ( m_xBrowserController.is() )
+ {
+ OSL_VERIFY( m_xBrowserController->getViewData() >>= sCurrentPage );
+ }
+
+ if ( !sCurrentPage.getLength() )
+ sCurrentPage = m_sLastActivePage;
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::getCurrentPage: caught an exception while retrieving the current page!" );
+ }
+ return sCurrentPage;
+}
+
+//-----------------------------------------------------------------------
+void FmPropBrw::implDetachController()
+{
+ m_sLastActivePage = getCurrentPage();
+
+ implSetNewSelection( InterfaceBag() );
+
+ if ( m_xMeAsFrame.is() )
+ {
+ try
+ {
+ m_xMeAsFrame->setComponent(NULL, NULL);
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::implDetachController: caught an exception while resetting the component!" );
+ }
+ }
+
+ // we attached a frame to the controller manually, so we need to manually tell it that it's detached, too
+ // 96068 - 09.01.2002 - fs@openoffice.org
+ if ( m_xBrowserController.is() )
+ m_xBrowserController->attachFrame( NULL );
+
+ m_xBrowserController.clear();
+ m_xInspectorModel.clear();
+ m_xMeAsFrame.clear();
+}
+
+//-----------------------------------------------------------------------
+sal_Bool FmPropBrw::Close()
+{
+ // suspend the controller (it is allowed to veto)
+ if ( m_xMeAsFrame.is() )
+ {
+ try
+ {
+ Reference< XController > xController( m_xMeAsFrame->getController() );
+ if ( xController.is() && !xController->suspend( sal_True ) )
+ return sal_False;
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::Close: caught an exception while asking the controller!" );
+ }
+ }
+
+ implDetachController();
+
+ if( IsRollUp() )
+ RollDown();
+
+ // remember our bindings: while we're closed, we're deleted, too, so accessing the bindings after this
+ // would be deadly
+ // 10/19/00 - 79321 - FS
+ SfxBindings& rBindings = SfxControllerItem::GetBindings();
+
+ sal_Bool bClose = SfxFloatingWindow::Close();
+
+ if (bClose)
+ {
+ rBindings.Invalidate(SID_FM_CTL_PROPERTIES);
+ rBindings.Invalidate(SID_FM_PROPERTIES);
+ }
+
+ return bClose;
+}
+
+//-----------------------------------------------------------------------
+bool FmPropBrw::implIsReadOnlyModel() const
+{
+ try
+ {
+ if ( m_xInspectorModel.is() )
+ return m_xInspectorModel->getIsReadOnly();
+ return false;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------
+void FmPropBrw::implSetNewSelection( const InterfaceBag& _rSelection )
+{
+ if ( m_xBrowserController.is() )
+ {
+ try
+ {
+ Reference< XObjectInspector > xInspector( m_xBrowserController, UNO_QUERY_THROW );
+
+ // tell it the objects to inspect
+ Sequence< Reference< XInterface > > aSelection( _rSelection.size() );
+ ::std::copy( _rSelection.begin(), _rSelection.end(), aSelection.getArray() );
+
+ xInspector->inspect( aSelection );
+ }
+ catch( const VetoException& )
+ {
+ return;
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::implSetNewSelection: caught an unexpected exception!" );
+ return;
+ }
+
+ // set the new title according to the selected object
+ String sTitle;
+
+ if ( _rSelection.empty() )
+ {
+ sTitle = String( SVX_RES( RID_STR_NO_PROPERTIES ) );
+ }
+ else if ( _rSelection.size() > 1 )
+ {
+ // no form component and (no form or no name) -> Multiselection
+ sTitle = String( SVX_RES( RID_STR_PROPERTIES_CONTROL ) );
+ sTitle += String( SVX_RES( RID_STR_PROPTITLE_MULTISELECT ) );
+ }
+ else
+ {
+ Reference< XPropertySet > xSingleSelection( *_rSelection.begin(), UNO_QUERY);
+ if ( ::comphelper::hasProperty( FM_PROP_CLASSID, xSingleSelection ) )
+ {
+ sal_Int16 nClassID = FormComponentType::CONTROL;
+ xSingleSelection->getPropertyValue( FM_PROP_CLASSID ) >>= nClassID;
+
+ sTitle = String( SVX_RES( RID_STR_PROPERTIES_CONTROL ) );
+ sTitle += String( GetUIHeadlineName( nClassID, makeAny( xSingleSelection ) ) );
+ }
+ else if ( Reference< XForm >( xSingleSelection, UNO_QUERY ).is() )
+ sTitle = String( SVX_RES( RID_STR_PROPERTIES_FORM ) );
+ }
+
+ if ( implIsReadOnlyModel() )
+ sTitle += String( SVX_RES( RID_STR_READONLY_VIEW ) );
+
+ SetText( sTitle );
+
+ // #95343# ---------------------------------
+ Reference< ::com::sun::star::awt::XLayoutConstrains > xLayoutConstrains( m_xBrowserController, UNO_QUERY );
+ if( xLayoutConstrains.is() )
+ {
+ ::Size aConstrainedSize;
+ ::com::sun::star::awt::Size aMinSize = xLayoutConstrains->getMinimumSize();
+
+ sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
+ GetBorder( nLeft, nTop, nRight, nBottom );
+ aMinSize.Width += nLeft + nRight + 8;
+ aMinSize.Height += nTop + nBottom + 8;
+
+ aConstrainedSize.setHeight( aMinSize.Height );
+ aConstrainedSize.setWidth( aMinSize.Width );
+ SetMinOutputSizePixel( aConstrainedSize );
+ aConstrainedSize = GetOutputSizePixel();
+ sal_Bool bResize = sal_False;
+ if( aConstrainedSize.Width() < aMinSize.Width )
+ {
+ aConstrainedSize.setWidth( aMinSize.Width );
+ bResize = sal_True;
+ }
+ if( aConstrainedSize.Height() < aMinSize.Height )
+ {
+ aConstrainedSize.setHeight( aMinSize.Height );
+ bResize = sal_True;
+ }
+ if( bResize )
+ SetOutputSizePixel( aConstrainedSize );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------
+void FmPropBrw::FillInfo( SfxChildWinInfo& rInfo ) const
+{
+ rInfo.bVisible = sal_False;
+ rInfo.aExtraString = getCurrentPage();
+}
+
+//-----------------------------------------------------------------------
+IMPL_LINK( FmPropBrw, OnAsyncGetFocus, void*, /*NOTINTERESTEDIN*/ )
+{
+ if (m_xBrowserComponentWindow.is())
+ m_xBrowserComponentWindow->setFocus();
+ return 0L;
+}
+
+//-----------------------------------------------------------------------
+namespace
+{
+ static bool lcl_shouldEnableHelpSection( const Reference< XMultiServiceFactory >& _rxFactory )
+ {
+ const ::rtl::OUString sConfigName( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Forms/PropertyBrowser/" ) );
+ const ::rtl::OUString sPropertyName( RTL_CONSTASCII_USTRINGPARAM( "DirectHelp" ) );
+
+ ::utl::OConfigurationTreeRoot aConfiguration(
+ ::utl::OConfigurationTreeRoot::createWithServiceFactory( _rxFactory, sConfigName ) );
+
+ bool bEnabled = false;
+ OSL_VERIFY( aConfiguration.getNodeValue( sPropertyName ) >>= bEnabled );
+ return bEnabled;
+ }
+}
+//-----------------------------------------------------------------------
+void FmPropBrw::impl_createPropertyBrowser_throw( FmFormShell* _pFormShell )
+{
+ // the document in which we live
+ Reference< XInterface > xDocument;
+ if ( _pFormShell && _pFormShell->GetObjectShell() )
+ xDocument = _pFormShell->GetObjectShell()->GetModel();
+
+ // the context of the controls in our document
+ Reference< awt::XControlContainer > xControlContext;
+ if ( _pFormShell && _pFormShell->GetFormView() )
+ {
+ SdrPageView* pPageView = _pFormShell->GetFormView()->GetSdrPageView();
+
+ if(pPageView)
+ {
+ SdrPageWindow* pPageWindow = pPageView->GetPageWindow(0L);
+
+ if(pPageWindow)
+ {
+ xControlContext = pPageWindow->GetControlContainer();
+ }
+ }
+ }
+
+ // the default parent window for message boxes
+ Reference< XWindow > xParentWindow( VCLUnoHelper::GetInterface ( this ) );
+
+ // the mapping from control models to control shapes
+ Reference< XMap > xControlMap;
+ FmFormPage* pFormPage = _pFormShell ? _pFormShell->GetCurPage() : NULL;
+ if ( pFormPage )
+ xControlMap = pFormPage->GetImpl().getControlToShapeMap();
+
+ // our own component context
+ Reference< XPropertySet > xFactoryProperties( m_xORB, UNO_QUERY_THROW );
+ Reference< XComponentContext > xOwnContext(
+ xFactoryProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ),
+ UNO_QUERY_THROW );
+
+ // a ComponentContext for the
+ ::cppu::ContextEntry_Init aHandlerContextInfo[] =
+ {
+ ::cppu::ContextEntry_Init( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContextDocument" ) ), makeAny( xDocument ) ),
+ ::cppu::ContextEntry_Init( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogParentWindow" ) ), makeAny( xParentWindow ) ),
+ ::cppu::ContextEntry_Init( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlContext" ) ), makeAny( xControlContext ) ),
+ ::cppu::ContextEntry_Init( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlShapeAccess" ) ), makeAny( xControlMap ) )
+ };
+ m_xInspectorContext.set(
+ ::cppu::createComponentContext( aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ),
+ xOwnContext ) );
+
+ bool bEnableHelpSection = lcl_shouldEnableHelpSection( m_xORB );
+
+ // an object inspector model
+ m_xInspectorModel =
+ bEnableHelpSection
+ ? DefaultFormComponentInspectorModel::createWithHelpSection( m_xInspectorContext, 3, 5 )
+ : DefaultFormComponentInspectorModel::createDefault( m_xInspectorContext );
+
+ // an object inspector
+ m_xBrowserController = m_xBrowserController.query(
+ ObjectInspector::createWithModel(
+ m_xInspectorContext, m_xInspectorModel
+ ) );
+
+ if ( !m_xBrowserController.is() )
+ {
+ ::rtl::OUString sServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.inspection.ObjectInspector" ) );
+ ShowServiceNotAvailableError( GetParent(), sServiceName, sal_True );
+ }
+ else
+ {
+ m_xBrowserController->attachFrame( m_xMeAsFrame );
+ m_xBrowserComponentWindow = m_xMeAsFrame->getComponentWindow();
+ DBG_ASSERT( m_xBrowserComponentWindow.is(), "FmPropBrw::impl_createPropertyBrowser_throw: attached the controller, but have no component window!" );
+ }
+
+ if ( bEnableHelpSection )
+ {
+ Reference< XObjectInspector > xInspector( m_xBrowserController, UNO_QUERY_THROW );
+ Reference< XObjectInspectorUI > xInspectorUI( xInspector->getInspectorUI() );
+ Reference< XInterface > xDefaultHelpProvider( DefaultHelpProvider::create( m_xInspectorContext, xInspectorUI ) );
+ }
+}
+
+//-----------------------------------------------------------------------
+void FmPropBrw::impl_ensurePropertyBrowser_nothrow( FmFormShell* _pFormShell )
+{
+ // the document in which we live
+ Reference< XInterface > xDocument;
+ SfxObjectShell* pObjectShell = _pFormShell ? _pFormShell->GetObjectShell() : NULL;
+ if ( pObjectShell )
+ xDocument = pObjectShell->GetModel();
+ if ( ( xDocument == m_xLastKnownDocument ) && m_xBrowserController.is() )
+ // nothing to do
+ return;
+
+ try
+ {
+ // clean up any previous instances of the object inspector
+ if ( m_xMeAsFrame.is() )
+ m_xMeAsFrame->setComponent( NULL, NULL );
+ else
+ ::comphelper::disposeComponent( m_xBrowserController );
+ m_xBrowserController.clear();
+ m_xInspectorModel.clear();
+ m_xBrowserComponentWindow.clear();
+
+ // and create a new one
+ impl_createPropertyBrowser_throw( _pFormShell );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ m_xLastKnownDocument = xDocument;
+}
+
+//-----------------------------------------------------------------------
+void FmPropBrw::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
+{
+ if (!pState || SID_FM_PROPERTY_CONTROL != nSID)
+ return;
+
+ m_bInStateChange = true;
+ try
+ {
+ if (eState >= SFX_ITEM_AVAILABLE)
+ {
+ FmFormShell* pShell = PTR_CAST(FmFormShell,((SfxObjectItem*)pState)->GetShell());
+ InterfaceBag aSelection;
+ if ( pShell )
+ pShell->GetImpl()->getCurrentSelection( aSelection );
+
+ impl_ensurePropertyBrowser_nothrow( pShell );
+
+ // set the new object to inspect
+ implSetNewSelection( aSelection );
+
+ // if this is the first time we're here, some additional things need to be done ...
+ if ( m_bInitialStateChange )
+ {
+ // if we're just newly created, we want to have the focus
+ PostUserEvent( LINK( this, FmPropBrw, OnAsyncGetFocus ) );
+
+ // and additionally, we want to show the page which was active during
+ // our previous incarnation
+ if ( m_sLastActivePage.getLength() )
+ {
+ try
+ {
+ if ( m_xBrowserController.is() )
+ m_xBrowserController->restoreViewData( makeAny( m_sLastActivePage ) );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmPropBrw::StateChanged: caught an exception while setting the initial page!" );
+ }
+ }
+
+ m_bInitialStateChange = sal_False;
+ }
+
+ }
+ else
+ {
+ implSetNewSelection( InterfaceBag() );
+ }
+ }
+ catch (Exception&)
+ {
+ DBG_ERROR("FmPropBrw::StateChanged: Exception occurred!");
+ }
+ m_bInStateChange = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmcontrolbordermanager.cxx b/svx/source/form/fmcontrolbordermanager.cxx
new file mode 100644
index 000000000000..e5120ab60266
--- /dev/null
+++ b/svx/source/form/fmcontrolbordermanager.cxx
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmcontrolbordermanager.hxx"
+
+#include "fmprop.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
+#include <com/sun/star/awt/XTextComponent.hpp>
+#include <com/sun/star/awt/XListBox.hpp>
+/** === end UNO includes === **/
+#include <tools/debug.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::form::validation;
+
+ //====================================================================
+ //= helper
+ //====================================================================
+ //--------------------------------------------------------------------
+ static void setUnderline( const Reference< XVclWindowPeer >& _rxPeer, const UnderlineDescriptor& _rUnderline )
+ {
+ OSL_ENSURE( _rxPeer.is(), "setUnderline: invalid peer!" );
+
+ // the underline type is an aspect of the font
+ FontDescriptor aFont;
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_FONT ) >>= aFont );
+ aFont.Underline = _rUnderline.nUnderlineType;
+ _rxPeer->setProperty( FM_PROP_FONT, makeAny( aFont ) );
+ // the underline color is a separate property
+ _rxPeer->setProperty( FM_PROP_TEXTLINECOLOR, makeAny( _rUnderline.nUnderlineColor ) );
+ }
+
+ //--------------------------------------------------------------------
+ static void getUnderline( const Reference< XVclWindowPeer >& _rxPeer, UnderlineDescriptor& _rUnderline )
+ {
+ OSL_ENSURE( _rxPeer.is(), "getUnderline: invalid peer!" );
+
+ FontDescriptor aFont;
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_FONT ) >>= aFont );
+ _rUnderline.nUnderlineType = aFont.Underline;
+
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_TEXTLINECOLOR ) >>= _rUnderline.nUnderlineColor );
+ }
+
+ //--------------------------------------------------------------------
+ static void getBorder( const Reference< XVclWindowPeer >& _rxPeer, BorderDescriptor& _rBoder )
+ {
+ OSL_ENSURE( _rxPeer.is(), "getBorder: invalid peer!" );
+
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDER ) >>= _rBoder.nBorderType );
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDERCOLOR ) >>= _rBoder.nBorderColor );
+ }
+
+ //--------------------------------------------------------------------
+ static void setBorder( const Reference< XVclWindowPeer >& _rxPeer, const BorderDescriptor& _rBoder )
+ {
+ OSL_ENSURE( _rxPeer.is(), "setBorder: invalid peer!" );
+
+ _rxPeer->setProperty( FM_PROP_BORDER, makeAny( _rBoder.nBorderType ) );
+ _rxPeer->setProperty( FM_PROP_BORDERCOLOR, makeAny( _rBoder.nBorderColor ) );
+ }
+
+ //====================================================================
+ //= ControlBorderManager
+ //====================================================================
+ //--------------------------------------------------------------------
+ ControlBorderManager::ControlBorderManager()
+ :m_nFocusColor ( 0x000000FF )
+ ,m_nMouseHoveColor( 0x007098BE )
+ ,m_nInvalidColor ( 0x00FF0000 )
+ ,m_bDynamicBorderColors( false )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ ControlBorderManager::~ControlBorderManager()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool ControlBorderManager::canColorBorder( const Reference< XVclWindowPeer >& _rxPeer )
+ {
+ OSL_PRECOND( _rxPeer.is(), "ControlBorderManager::canColorBorder: invalid peer!" );
+
+ PeerBag::const_iterator aPos = m_aColorableControls.find( _rxPeer );
+ if ( aPos != m_aColorableControls.end() )
+ return true;
+
+ aPos = m_aNonColorableControls.find( _rxPeer );
+ if ( aPos != m_aNonColorableControls.end() )
+ return false;
+
+ // this peer is not yet known
+
+ // no border coloring for controls which are not for text input
+ // #i37434# / 2004-11-19 / frank.schoenheit@sun.com
+ Reference< XTextComponent > xText( _rxPeer, UNO_QUERY );
+ Reference< XListBox > xListBox( _rxPeer, UNO_QUERY );
+ if ( xText.is() || xListBox.is() )
+ {
+ sal_Int16 nBorderStyle = VisualEffect::NONE;
+ OSL_VERIFY( _rxPeer->getProperty( FM_PROP_BORDER ) >>= nBorderStyle );
+ if ( nBorderStyle == VisualEffect::FLAT )
+ // if you change this to also accept LOOK3D, then this would also work, but look ugly
+ {
+ m_aColorableControls.insert( _rxPeer );
+ return true;
+ }
+ }
+
+ m_aNonColorableControls.insert( _rxPeer );
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ ControlStatus ControlBorderManager::getControlStatus( const Reference< XControl >& _rxControl ) SAL_THROW(())
+ {
+ ControlStatus nStatus = CONTROL_STATUS_NONE;
+
+ if ( _rxControl.get() == m_aFocusControl.xControl.get() )
+ nStatus |= CONTROL_STATUS_FOCUSED;
+
+ if ( _rxControl.get() == m_aMouseHoverControl.xControl.get() )
+ nStatus |= CONTROL_STATUS_MOUSE_HOVER;
+
+ if ( m_aInvalidControls.find( ControlData( _rxControl ) ) != m_aInvalidControls.end() )
+ nStatus |= CONTROL_STATUS_INVALID;
+
+ return nStatus;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 ControlBorderManager::getControlColorByStatus( ControlStatus _nStatus )
+ {
+ // "invalid" is ranked highest
+ if ( _nStatus & CONTROL_STATUS_INVALID )
+ return m_nInvalidColor;
+
+ // then, "focused" is more important than ...
+ if ( _nStatus & CONTROL_STATUS_FOCUSED )
+ return m_nFocusColor;
+
+ // ... "mouse over"
+ if ( _nStatus & CONTROL_STATUS_MOUSE_HOVER )
+ return m_nMouseHoveColor;
+
+ OSL_ENSURE( sal_False, "ControlBorderManager::getControlColorByStatus: invalid status!" );
+ return 0x00000000;
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::updateBorderStyle( const Reference< XControl >& _rxControl, const Reference< XVclWindowPeer >& _rxPeer, const BorderDescriptor& _rFallback ) SAL_THROW(())
+ {
+ OSL_PRECOND( _rxControl.is() && _rxPeer.is(), "ControlBorderManager::updateBorderStyle: invalid parameters!" );
+
+ ControlStatus nStatus = getControlStatus( _rxControl );
+ BorderDescriptor aBorder;
+ aBorder.nBorderType = ( nStatus == CONTROL_STATUS_NONE )
+ ? _rFallback.nBorderType
+ : VisualEffect::FLAT;
+ aBorder.nBorderColor = ( nStatus == CONTROL_STATUS_NONE )
+ ? _rFallback.nBorderColor
+ : getControlColorByStatus( nStatus );
+ setBorder( _rxPeer, aBorder );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::determineOriginalBorderStyle( const Reference< XControl >& _rxControl, BorderDescriptor& _rData ) const
+ {
+ _rData = ControlData();
+ if ( m_aFocusControl.xControl.get() == _rxControl.get() )
+ {
+ _rData = m_aFocusControl;
+ }
+ else if ( m_aMouseHoverControl.xControl.get() == _rxControl.get() )
+ {
+ _rData = m_aMouseHoverControl;
+ }
+ else
+ {
+ ControlBag::const_iterator aPos = m_aInvalidControls.find( _rxControl );
+ if ( aPos != m_aInvalidControls.end() )
+ {
+ _rData = *aPos;
+ }
+ else
+ {
+ Reference< XVclWindowPeer > xPeer( _rxControl->getPeer(), UNO_QUERY );
+ getBorder( xPeer, _rData );
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::controlStatusGained( const Reference< XInterface >& _rxControl, ControlData& _rControlData ) SAL_THROW(())
+ {
+ if ( _rxControl == _rControlData.xControl )
+ // nothing to do - though suspicious
+ return;
+
+ Reference< XControl > xAsControl( _rxControl, UNO_QUERY );
+ DBG_ASSERT( xAsControl.is(), "ControlBorderManager::controlStatusGained: invalid control!" );
+ if ( !xAsControl.is() )
+ return;
+
+ try
+ {
+ Reference< XVclWindowPeer > xPeer( xAsControl->getPeer(), UNO_QUERY );
+ if ( xPeer.is() && canColorBorder( xPeer ) )
+ {
+ // remember the control and it's current border color
+ _rControlData.xControl.clear(); // so determineOriginalBorderStyle doesn't get confused
+
+ determineOriginalBorderStyle( xAsControl, _rControlData );
+
+ _rControlData.xControl = xAsControl;
+
+ updateBorderStyle( xAsControl, xPeer, _rControlData );
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "ControlBorderManager::controlStatusGained: caught an exception!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::controlStatusLost( const Reference< XInterface >& _rxControl, ControlData& _rControlData ) SAL_THROW(())
+ {
+ if ( _rxControl != _rControlData.xControl )
+ // nothing to do
+ return;
+
+ OSL_PRECOND( _rControlData.xControl.is(), "ControlBorderManager::controlStatusLost: invalid control data - this will crash!" );
+ try
+ {
+ Reference< XVclWindowPeer > xPeer( _rControlData.xControl->getPeer(), UNO_QUERY );
+ if ( xPeer.is() && canColorBorder( xPeer ) )
+ {
+ ControlData aPreviousStatus( _rControlData );
+ _rControlData = ControlData();
+ updateBorderStyle( aPreviousStatus.xControl, xPeer, aPreviousStatus );
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "ControlBorderManager::controlStatusLost: caught an exception!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::enableDynamicBorderColor( )
+ {
+ m_bDynamicBorderColors = true;
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::disableDynamicBorderColor( )
+ {
+ m_bDynamicBorderColors = false;
+ restoreAll();
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::setStatusColor( ControlStatus _nStatus, sal_Int32 _nColor )
+ {
+ switch ( _nStatus )
+ {
+ case CONTROL_STATUS_FOCUSED:
+ m_nFocusColor = _nColor;
+ break;
+ case CONTROL_STATUS_MOUSE_HOVER:
+ m_nMouseHoveColor = _nColor;
+ break;
+ case CONTROL_STATUS_INVALID:
+ m_nInvalidColor = _nColor;
+ break;
+ default:
+ OSL_ENSURE( sal_False, "ControlBorderManager::setStatusColor: invalid status!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::restoreAll()
+ {
+ if ( m_aFocusControl.xControl.is() )
+ controlStatusLost( m_aFocusControl.xControl, m_aFocusControl );
+ if ( m_aMouseHoverControl.xControl.is() )
+ controlStatusLost( m_aMouseHoverControl.xControl, m_aMouseHoverControl );
+
+ ControlBag aInvalidControls;
+ m_aInvalidControls.swap( aInvalidControls );
+
+ for ( ControlBag::const_iterator loop = aInvalidControls.begin();
+ loop != aInvalidControls.end();
+ ++loop
+ )
+ {
+ Reference< XVclWindowPeer > xPeer( loop->xControl->getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ {
+ updateBorderStyle( loop->xControl, xPeer, *loop );
+ xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( loop->sOriginalHelpText ) );
+ setUnderline( xPeer, *loop );
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::focusGained( const Reference< XInterface >& _rxControl ) SAL_THROW(())
+ {
+ if ( m_bDynamicBorderColors )
+ controlStatusGained( _rxControl, m_aFocusControl );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::focusLost( const Reference< XInterface >& _rxControl ) SAL_THROW(())
+ {
+ if ( m_bDynamicBorderColors )
+ controlStatusLost( _rxControl, m_aFocusControl );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::mouseEntered( const Reference< XInterface >& _rxControl ) SAL_THROW(())
+ {
+ if ( m_bDynamicBorderColors )
+ controlStatusGained( _rxControl, m_aMouseHoverControl );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::mouseExited( const Reference< XInterface >& _rxControl ) SAL_THROW(())
+ {
+ if ( m_bDynamicBorderColors )
+ controlStatusLost( _rxControl, m_aMouseHoverControl );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlBorderManager::validityChanged( const Reference< XControl >& _rxControl, const Reference< XValidatableFormComponent >& _rxValidatable ) SAL_THROW(())
+ {
+ try
+ {
+ OSL_ENSURE( _rxControl.is(), "ControlBorderManager::validityChanged: invalid control!" );
+ OSL_ENSURE( _rxValidatable.is(), "ControlBorderManager::validityChanged: invalid validatable!" );
+
+ Reference< XVclWindowPeer > xPeer( _rxControl.is() ? _rxControl->getPeer() : Reference< XWindowPeer >(), UNO_QUERY );
+ if ( !xPeer.is() || !_rxValidatable.is() )
+ return;
+
+ ControlData aData( _rxControl );
+
+ if ( _rxValidatable->isValid() )
+ {
+ ControlBag::iterator aPos = m_aInvalidControls.find( aData );
+ if ( aPos != m_aInvalidControls.end() )
+ { // invalid before, valid now
+ ControlData aOriginalLayout( *aPos );
+ m_aInvalidControls.erase( aPos );
+
+ // restore all the things we used to indicate invalidity
+ if ( m_bDynamicBorderColors )
+ updateBorderStyle( _rxControl, xPeer, aOriginalLayout );
+ xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( aOriginalLayout.sOriginalHelpText ) );
+ setUnderline( xPeer, aOriginalLayout );
+ }
+ return;
+ }
+
+ // we're here in the INVALID case
+ if ( m_aInvalidControls.find( _rxControl ) == m_aInvalidControls.end() )
+ { // valid before, invalid now
+
+ // remember the current border
+ determineOriginalBorderStyle( _rxControl, aData );
+ // and tool tip
+ xPeer->getProperty( FM_PROP_HELPTEXT ) >>= aData.sOriginalHelpText;
+ // and font
+ getUnderline( xPeer, aData );
+
+ m_aInvalidControls.insert( aData );
+
+ // update the border to the new invalidity
+ if ( m_bDynamicBorderColors && canColorBorder( xPeer ) )
+ updateBorderStyle( _rxControl, xPeer, aData );
+ else
+ {
+ // and also the new font
+ setUnderline( xPeer, UnderlineDescriptor( com::sun::star::awt::FontUnderline::WAVE, m_nInvalidColor ) );
+ }
+ }
+
+ // update the explanation for invalidity (this is always done, even if the validity did not change)
+ Reference< XValidator > xValidator = _rxValidatable->getValidator();
+ OSL_ENSURE( xValidator.is(), "ControlBorderManager::validityChanged: invalid, but no validator?" );
+ ::rtl::OUString sExplainInvalidity = xValidator.is() ? xValidator->explainInvalid( _rxValidatable->getCurrentValue() ) : ::rtl::OUString();
+ xPeer->setProperty( FM_PROP_HELPTEXT, makeAny( sExplainInvalidity ) );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "ControlBorderManager::validityChanged: caught an exception!" );
+ }
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmcontrollayout.cxx b/svx/source/form/fmcontrollayout.cxx
new file mode 100644
index 000000000000..5c590448b789
--- /dev/null
+++ b/svx/source/form/fmcontrollayout.cxx
@@ -0,0 +1,331 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmcontrollayout.hxx"
+#include "fmprop.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/container/XChild.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/processfactory.hxx>
+#include <i18npool/mslangid.hxx>
+#include <unotools/syslocale.hxx>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/outdev.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::utl;
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::lang::Locale;
+ using ::com::sun::star::awt::FontDescriptor;
+ using ::com::sun::star::style::XStyleFamiliesSupplier;
+ using ::com::sun::star::lang::XServiceInfo;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::container::XChild;
+ /** === end UNO using === **/
+ namespace FormComponentType = ::com::sun::star::form::FormComponentType;
+ namespace VisualEffect = ::com::sun::star::awt::VisualEffect;
+ namespace ScriptType = ::com::sun::star::i18n::ScriptType;
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ //....................................................................
+ template< class INTERFACE_TYPE >
+ Reference< INTERFACE_TYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode )
+ {
+ Reference< INTERFACE_TYPE > xTypedNode( _rxModelNode, UNO_QUERY );
+ if ( xTypedNode.is() )
+ return xTypedNode;
+ else
+ {
+ Reference< XChild > xChild( _rxModelNode, UNO_QUERY );
+ if ( xChild.is() )
+ return getTypedModelNode< INTERFACE_TYPE >( xChild->getParent() );
+ else
+ return NULL;
+ }
+ }
+
+ //....................................................................
+ static bool lcl_getDocumentDefaultStyleAndFamily( const Reference< XInterface >& _rxDocument, ::rtl::OUString& _rFamilyName, ::rtl::OUString& _rStyleName ) SAL_THROW(( Exception ))
+ {
+ bool bSuccess = true;
+ Reference< XServiceInfo > xDocumentSI( _rxDocument, UNO_QUERY );
+ if ( xDocumentSI.is() )
+ {
+ if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ) )
+ || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.WebDocument" ) ) )
+ )
+ {
+ _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParagraphStyles" ) );
+ _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
+ }
+ else if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ) ) ) )
+ {
+ _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CellStyles" ) );
+ _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) );
+ }
+ else if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) )
+ || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) )
+ )
+ {
+ _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "graphics" ) );
+ _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "standard" ) );
+ }
+ else
+ bSuccess = false;
+ }
+ return bSuccess;
+ }
+
+ //....................................................................
+ static void lcl_initializeControlFont( const Reference< XPropertySet >& _rxModel )
+ {
+ try
+ {
+ Reference< XPropertySet > xStyle( ControlLayouter::getDefaultDocumentTextStyle( _rxModel ), UNO_SET_THROW );
+ Reference< XPropertySetInfo > xStylePSI( xStyle->getPropertySetInfo(), UNO_SET_THROW );
+
+ // determine the script type associated with the system locale
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rSysLocaleData = aSysLocale.GetLocaleData();
+ const sal_Int16 eSysLocaleScriptType = MsLangId::getScriptType( MsLangId::convertLocaleToLanguage( rSysLocaleData.getLocale() ) );
+
+ // depending on this script type, use the right property from the document's style which controls the
+ // default locale for document content
+ const sal_Char* pCharLocalePropertyName = "CharLocale";
+ switch ( eSysLocaleScriptType )
+ {
+ case ScriptType::LATIN:
+ // already defaulted above
+ break;
+ case ScriptType::ASIAN:
+ pCharLocalePropertyName = "CharLocaleAsian";
+ break;
+ case ScriptType::COMPLEX:
+ pCharLocalePropertyName = "CharLocaleComplex";
+ break;
+ default:
+ OSL_ENSURE( false, "lcl_initializeControlFont: unexpected script type for system locale!" );
+ break;
+ }
+
+ ::rtl::OUString sCharLocalePropertyName = ::rtl::OUString::createFromAscii( pCharLocalePropertyName );
+ Locale aDocumentCharLocale;
+ if ( xStylePSI->hasPropertyByName( sCharLocalePropertyName ) )
+ {
+ OSL_VERIFY( xStyle->getPropertyValue( sCharLocalePropertyName ) >>= aDocumentCharLocale );
+ }
+ // fall back to CharLocale property at the style
+ if ( !aDocumentCharLocale.Language.getLength() )
+ {
+ sCharLocalePropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharLocale" ) );
+ if ( xStylePSI->hasPropertyByName( sCharLocalePropertyName ) )
+ {
+ OSL_VERIFY( xStyle->getPropertyValue( sCharLocalePropertyName ) >>= aDocumentCharLocale );
+ }
+ }
+ // fall back to the system locale
+ if ( !aDocumentCharLocale.Language.getLength() )
+ {
+ aDocumentCharLocale = rSysLocaleData.getLocale();
+ }
+
+ // retrieve a default font for this locale, and set it at the control
+ Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS, MsLangId::convertLocaleToLanguage( aDocumentCharLocale ), DEFAULTFONT_FLAGS_ONLYONE );
+ FontDescriptor aFontDesc = VCLUnoHelper::CreateFontDescriptor( aFont );
+ _rxModel->setPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FontDescriptor" ) ),
+ makeAny( aFontDesc )
+ );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+
+ //====================================================================
+ //= ControlLayouter
+ //====================================================================
+ //--------------------------------------------------------------------
+ Reference< XPropertySet > ControlLayouter::getDefaultDocumentTextStyle( const Reference< XPropertySet >& _rxModel )
+ {
+ // the style family collection
+ Reference< XStyleFamiliesSupplier > xSuppStyleFamilies( getTypedModelNode< XStyleFamiliesSupplier >( _rxModel.get() ), UNO_SET_THROW );
+ Reference< XNameAccess > xStyleFamilies( xSuppStyleFamilies->getStyleFamilies(), UNO_SET_THROW );
+
+ // the names of the family, and the style - depends on the document type we live in
+ ::rtl::OUString sFamilyName, sStyleName;
+ if ( !lcl_getDocumentDefaultStyleAndFamily( xSuppStyleFamilies.get(), sFamilyName, sStyleName ) )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown document type!" ) ), NULL );
+
+ // the concrete style
+ Reference< XNameAccess > xStyleFamily( xStyleFamilies->getByName( sFamilyName ), UNO_QUERY_THROW );
+ return Reference< XPropertySet >( xStyleFamily->getByName( sStyleName ), UNO_QUERY_THROW );
+ }
+
+ //--------------------------------------------------------------------
+ void ControlLayouter::initializeControlLayout( const Reference< XPropertySet >& _rxControlModel, DocumentType _eDocType )
+ {
+ DBG_ASSERT( _rxControlModel.is(), "ControlLayouter::initializeControlLayout: invalid model!" );
+ if ( !_rxControlModel.is() )
+ return;
+
+ try
+ {
+ Reference< XPropertySetInfo > xPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
+
+ // the control type
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+ _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId;
+
+ // the document type
+ if ( _eDocType == eUnknownDocumentType )
+ _eDocType = DocumentClassification::classifyHostDocument( _rxControlModel.get() );
+
+ // let's see what the configuration says about the visual effect
+ OConfigurationNode aConfig = getLayoutSettings( _eDocType );
+ Any aVisualEffect = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualEffect" ) ) );
+ if ( aVisualEffect.hasValue() )
+ {
+ ::rtl::OUString sVisualEffect;
+ OSL_VERIFY( aVisualEffect >>= sVisualEffect );
+
+ sal_Int16 nVisualEffect = VisualEffect::NONE;
+ if ( sVisualEffect.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "flat" ) ) )
+ nVisualEffect = VisualEffect::FLAT;
+ else if ( sVisualEffect.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "3D" ) ) )
+ nVisualEffect = VisualEffect::LOOK3D;
+
+ if ( xPSI->hasPropertyByName( FM_PROP_BORDER ) )
+ {
+ if ( ( nClassId != FormComponentType::COMMANDBUTTON )
+ && ( nClassId != FormComponentType::RADIOBUTTON )
+ && ( nClassId != FormComponentType::CHECKBOX )
+ && ( nClassId != FormComponentType::GROUPBOX )
+ && ( nClassId != FormComponentType::FIXEDTEXT )
+ && ( nClassId != FormComponentType::SCROLLBAR )
+ && ( nClassId != FormComponentType::SPINBUTTON )
+ )
+ {
+ _rxControlModel->setPropertyValue( FM_PROP_BORDER, makeAny( nVisualEffect ) );
+ if ( ( nVisualEffect == VisualEffect::FLAT )
+ && ( xPSI->hasPropertyByName( FM_PROP_BORDERCOLOR ) )
+ )
+ // light gray flat border
+ _rxControlModel->setPropertyValue( FM_PROP_BORDERCOLOR, makeAny( (sal_Int32)0x00C0C0C0 ) );
+ }
+ }
+ if ( xPSI->hasPropertyByName( FM_PROP_VISUALEFFECT ) )
+ _rxControlModel->setPropertyValue( FM_PROP_VISUALEFFECT, makeAny( nVisualEffect ) );
+ }
+
+ // the font (only if we use the document's ref devices for rendering control text, otherwise, the
+ // default font of VCL controls is assumed to be fine)
+ if ( useDocumentReferenceDevice( _eDocType )
+ && xPSI->hasPropertyByName( FM_PROP_FONT )
+ )
+ lcl_initializeControlFont( _rxControlModel );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "ControlLayouter::initializeControlLayout: caught an exception!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ ::utl::OConfigurationNode ControlLayouter::getLayoutSettings( DocumentType _eDocType )
+ {
+ ::rtl::OUString sConfigName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Forms/ControlLayout/" ) );
+ sConfigName += DocumentClassification::getModuleIdentifierForDocumentType( _eDocType );
+ return OConfigurationTreeRoot::createWithServiceFactory(
+ ::comphelper::getProcessServiceFactory(), // TODO
+ sConfigName );
+ }
+
+ //--------------------------------------------------------------------
+ bool ControlLayouter::useDynamicBorderColor( DocumentType _eDocType )
+ {
+ OConfigurationNode aConfig = getLayoutSettings( _eDocType );
+ Any aDynamicBorderColor = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DynamicBorderColors" ) ) );
+ bool bDynamicBorderColor = false;
+ OSL_VERIFY( aDynamicBorderColor >>= bDynamicBorderColor );
+ return bDynamicBorderColor;
+ }
+
+ //--------------------------------------------------------------------
+ bool ControlLayouter::useDocumentReferenceDevice( DocumentType _eDocType )
+ {
+ if ( _eDocType == eUnknownDocumentType )
+ return false;
+ OConfigurationNode aConfig = getLayoutSettings( _eDocType );
+ Any aUseRefDevice = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentTextMetrics" ) ) );
+ bool bUseRefDevice = false;
+ OSL_VERIFY( aUseRefDevice >>= bUseRefDevice );
+ return bUseRefDevice;
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmdmod.cxx b/svx/source/form/fmdmod.cxx
new file mode 100644
index 000000000000..807919e60a2f
--- /dev/null
+++ b/svx/source/form/fmdmod.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <sal/macros.h>
+#include <svx/fmdmod.hxx>
+#include "fmservs.hxx"
+#include <fmobj.hxx>
+#include <svx/unoshape.hxx>
+#include <comphelper/processfactory.hxx>
+#include <svx/fmglob.hxx>
+
+using namespace ::svxform;
+
+//-----------------------------------------------------------------------------
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SvxFmMSFactory::createInstance(const ::rtl::OUString& ServiceSpecifier) throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
+ if ( ServiceSpecifier.indexOf( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.component.")) ) == 0 )
+ {
+ xRet = ::comphelper::getProcessServiceFactory()->createInstance(ServiceSpecifier);
+ }
+ else if ( ServiceSpecifier == ::rtl::OUString( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ControlShape")) ) )
+ {
+ SdrObject* pObj = new FmFormObj(OBJ_FM_CONTROL);
+ xRet = *new SvxShapeControl(pObj);
+ }
+ if (!xRet.is())
+ xRet = SvxUnoDrawMSFactory::createInstance(ServiceSpecifier);
+ return xRet;
+}
+
+//-----------------------------------------------------------------------------
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SvxFmMSFactory::createInstanceWithArguments(const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments) throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException )
+{
+ return SvxUnoDrawMSFactory::createInstanceWithArguments(ServiceSpecifier, Arguments );
+}
+
+//-----------------------------------------------------------------------------
+::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL SvxFmMSFactory::getAvailableServiceNames(void) throw( ::com::sun::star::uno::RuntimeException )
+{
+ static const ::rtl::OUString aSvxComponentServiceNameList[] =
+ {
+ FM_SUN_COMPONENT_TEXTFIELD,
+ FM_SUN_COMPONENT_FORM,
+ FM_SUN_COMPONENT_LISTBOX,
+ FM_SUN_COMPONENT_COMBOBOX,
+ FM_SUN_COMPONENT_RADIOBUTTON,
+ FM_SUN_COMPONENT_GROUPBOX,
+ FM_SUN_COMPONENT_FIXEDTEXT,
+ FM_SUN_COMPONENT_COMMANDBUTTON,
+ FM_SUN_COMPONENT_CHECKBOX,
+ FM_SUN_COMPONENT_GRIDCONTROL,
+ FM_SUN_COMPONENT_IMAGEBUTTON,
+ FM_SUN_COMPONENT_FILECONTROL,
+ FM_SUN_COMPONENT_TIMEFIELD,
+ FM_SUN_COMPONENT_DATEFIELD,
+ FM_SUN_COMPONENT_NUMERICFIELD,
+ FM_SUN_COMPONENT_CURRENCYFIELD,
+ FM_SUN_COMPONENT_PATTERNFIELD,
+ FM_SUN_COMPONENT_HIDDENCONTROL,
+ FM_SUN_COMPONENT_IMAGECONTROL
+ };
+
+ static const sal_uInt16 nSvxComponentServiceNameListCount = SAL_N_ELEMENTS(aSvxComponentServiceNameList);
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > aSeq( nSvxComponentServiceNameListCount );
+ ::rtl::OUString* pStrings = aSeq.getArray();
+ for( sal_uInt16 nIdx = 0; nIdx < nSvxComponentServiceNameListCount; nIdx++ )
+ pStrings[nIdx] = aSvxComponentServiceNameList[nIdx];
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > aParentSeq( SvxUnoDrawMSFactory::getAvailableServiceNames() );
+ return concatServiceNames( aParentSeq, aSeq );
+}
+
+/*
+// XServiceManager
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SvxFmDrawModel::createInstance(const ::rtl::OUString& ServiceName)
+ const throw( ::com::sun::star::lang::ServiceNotRegisteredException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
+ sal_uInt16 nTokenCount = ServiceName.getTokenCount('.');
+ if (nTokenCount == 5 &&
+ ServiceName.getToken( 0, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("stardiv")) &&
+ ServiceName.getToken( 1, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("one")) &&
+ ServiceName.getToken( 2, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("form")) &&
+ ServiceName.getToken( 3, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("component")) )
+ {
+ xRet = ::comphelper::getProcessServiceFactory()->createInstance(ServiceName);
+ }
+ else
+ if (nTokenCount == 4 &&
+ ServiceName.getToken( 0, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("stardiv")) &&
+ ServiceName.getToken( 1, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("one")) &&
+ ServiceName.getToken( 2, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("drawing")) &&
+ ServiceName.getToken( 3, '.' ) == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ControlShape")) )
+ {
+ SdrObject* pObj = new FmFormObj();
+ xRet = *new SvxShapeControl(pObj);
+ }
+ if (!xRet.is())
+ xRet = SvxUnoDrawModel::createInstance(ServiceName);
+ return xRet;
+}
+*/
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmdocumentclassification.cxx b/svx/source/form/fmdocumentclassification.cxx
new file mode 100644
index 000000000000..34083dae5108
--- /dev/null
+++ b/svx/source/form/fmdocumentclassification.cxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmdocumentclassification.hxx"
+#include "svx/dbtoolsclient.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xforms/XFormsSupplier.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+/** === end UNO includes === **/
+
+#include <tools/diagnose_ex.h>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ namespace
+ {
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::frame::XModule;
+
+ //....................................................................
+ template< class TYPE >
+ Reference< TYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode )
+ {
+ Reference< TYPE > xTypedNode( _rxModelNode, UNO_QUERY );
+ if ( xTypedNode.is() )
+ return xTypedNode;
+ else
+ {
+ Reference< XChild > xChild( _rxModelNode, UNO_QUERY );
+ if ( xChild.is() )
+ return getTypedModelNode< TYPE >( xChild->getParent() );
+ else
+ return Reference< TYPE >();
+ }
+ }
+
+ //....................................................................
+ Reference< XModel > getDocument( const Reference< XInterface >& _rxModelNode )
+ {
+ return getTypedModelNode< XModel >( _rxModelNode );
+ }
+ }
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::xforms;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::sdbc;
+
+ //====================================================================
+ //====================================================================
+ namespace
+ {
+ //----------------------------------------------------------------
+ struct ModuleInfo
+ {
+ const sal_Char* pAsciiModuleOrServiceName;
+ DocumentType eType;
+ };
+
+ //----------------------------------------------------------------
+ const ModuleInfo* lcl_getModuleInfo()
+ {
+ static const ModuleInfo aModuleInfo[] =
+ {
+ { "com.sun.star.text.TextDocument", eTextDocument },
+ { "com.sun.star.text.WebDocument", eWebDocument },
+ { "com.sun.star.sheet.SpreadsheetDocument", eSpreadsheetDocument },
+ { "com.sun.star.drawing.DrawingDocument", eDrawingDocument },
+ { "com.sun.star.presentation.PresentationDocument", ePresentationDocument },
+ { "com.sun.star.xforms.XMLFormDocument", eEnhancedForm },
+ { "com.sun.star.sdb.FormDesign", eDatabaseForm },
+ { "com.sun.star.sdb.TextReportDesign", eDatabaseReport },
+ { "com.sun.star.text.GlobalDocument", eTextDocument },
+ { NULL, eUnknownDocumentType }
+ };
+ return aModuleInfo;
+ }
+ }
+
+ //====================================================================
+ //= DocumentClassification
+ //====================================================================
+ //--------------------------------------------------------------------
+ DocumentType DocumentClassification::classifyDocument( const Reference< XModel >& _rxDocumentModel ) SAL_THROW(())
+ {
+ DocumentType eType( eUnknownDocumentType );
+
+ OSL_ENSURE( _rxDocumentModel.is(), "DocumentClassification::classifyDocument: invalid document!" );
+ if ( !_rxDocumentModel.is() )
+ return eType;
+
+ try
+ {
+ // first, check whether the document has a ModuleIdentifier which we know
+ ::rtl::OUString sModuleIdentifier;
+ Reference< XModule > xModule( _rxDocumentModel, UNO_QUERY );
+ if ( xModule.is() )
+ eType = getDocumentTypeForModuleIdentifier( xModule->getIdentifier() );
+ if ( eType != eUnknownDocumentType )
+ return eType;
+
+ // second, check whether it supports one of the services we know
+ Reference< XServiceInfo > xSI( _rxDocumentModel, UNO_QUERY_THROW );
+ const ModuleInfo* pModuleInfo = lcl_getModuleInfo();
+ while ( pModuleInfo->pAsciiModuleOrServiceName )
+ {
+ if ( xSI->supportsService( ::rtl::OUString::createFromAscii( pModuleInfo->pAsciiModuleOrServiceName ) ) )
+ return pModuleInfo->eType;
+ ++pModuleInfo;
+ }
+
+ // last: uhm, there is no last resort
+ OSL_ENSURE( false, "DocumentClassification::classifyDocument: unknown document!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return eType;
+ }
+
+ //--------------------------------------------------------------------
+ DocumentType DocumentClassification::classifyHostDocument( const Reference< XInterface >& _rxFormComponent ) SAL_THROW(())
+ {
+ DocumentType eType( eUnknownDocumentType );
+
+ try
+ {
+ Reference< XModel > xDocument( getDocument( _rxFormComponent.get() ) );
+ if ( !xDocument.is() )
+ return eUnknownDocumentType;
+ eType = classifyDocument( xDocument );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "DocumentClassification::classifyHostDocument: caught an exception!" );
+ }
+
+ return eType;
+ }
+
+ //--------------------------------------------------------------------
+ DocumentType DocumentClassification::getDocumentTypeForModuleIdentifier( const ::rtl::OUString& _rModuleIdentifier )
+ {
+ const ModuleInfo* pModuleInfo = lcl_getModuleInfo();
+ while ( pModuleInfo->pAsciiModuleOrServiceName )
+ {
+ if ( _rModuleIdentifier.equalsAscii( pModuleInfo->pAsciiModuleOrServiceName ) )
+ return pModuleInfo->eType;
+ ++pModuleInfo;
+ }
+ return eUnknownDocumentType;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString DocumentClassification::getModuleIdentifierForDocumentType( DocumentType _eType )
+ {
+ const ModuleInfo* pModuleInfo = lcl_getModuleInfo();
+ while ( pModuleInfo->pAsciiModuleOrServiceName )
+ {
+ if ( pModuleInfo->eType == _eType )
+ return ::rtl::OUString::createFromAscii( pModuleInfo->pAsciiModuleOrServiceName );
+ ++pModuleInfo;
+ }
+ return ::rtl::OUString();
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmdpage.cxx b/svx/source/form/fmdpage.cxx
new file mode 100644
index 000000000000..1581576f7657
--- /dev/null
+++ b/svx/source/form/fmdpage.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/fmpage.hxx>
+#include "fmobj.hxx"
+#include <svx/fmglob.hxx>
+#include <svx/fmdpage.hxx>
+#include <svx/unoshape.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::form::XFormsSupplier2;
+
+DBG_NAME(SvxFmDrawPage)
+SvxFmDrawPage::SvxFmDrawPage( SdrPage* pInPage ) :
+ SvxDrawPage( pInPage )
+{
+ DBG_CTOR(SvxFmDrawPage,NULL);
+}
+
+SvxFmDrawPage::~SvxFmDrawPage() throw ()
+{
+ DBG_DTOR(SvxFmDrawPage,NULL);
+}
+
+::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL SvxFmDrawPage::getImplementationId() throw(::com::sun::star::uno::RuntimeException)
+{
+ static ::cppu::OImplementationId* pId = 0;
+ if (! pId)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if (! pId)
+ {
+ static ::cppu::OImplementationId aId;
+ pId = &aId;
+ }
+ }
+ return pId->getImplementationId();
+}
+
+Any SAL_CALL SvxFmDrawPage::queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw(RuntimeException)
+{
+ Any aRet = ::cppu::queryInterface ( _rType
+ , static_cast< XFormsSupplier2* >( this )
+ , static_cast< XFormsSupplier* >( this )
+ );
+ if ( !aRet.hasValue() )
+ aRet = SvxDrawPage::queryAggregation( _rType );
+
+ return aRet;
+}
+
+/***********************************************************************
+* *
+***********************************************************************/
+::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL SvxFmDrawPage::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
+{
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > aTypes(SvxDrawPage::getTypes());
+ aTypes.realloc(aTypes.getLength() + 1);
+ ::com::sun::star::uno::Type* pTypes = aTypes.getArray();
+
+ pTypes[aTypes.getLength()-1] = ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormsSupplier>*)0);
+ return aTypes;
+}
+
+SdrObject *SvxFmDrawPage::_CreateSdrObject( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & xDescr ) throw ()
+{
+ ::rtl::OUString aShapeType( xDescr->getShapeType() );
+
+ if ( aShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.ShapeControl" ) ) // compatibility
+ || aShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.ControlShape" ) )
+ )
+ return new FmFormObj( OBJ_FM_CONTROL );
+ else
+ return SvxDrawPage::_CreateSdrObject( xDescr );
+
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > SvxFmDrawPage::_CreateShape( SdrObject *pObj ) const throw ()
+{
+ if( FmFormInventor == pObj->GetObjInventor() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape = (SvxShape*)new SvxShapeControl( pObj );
+ return xShape;
+ }
+ else
+ return SvxDrawPage::_CreateShape( pObj );
+}
+
+// XFormsSupplier
+::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > SAL_CALL SvxFmDrawPage::getForms(void) throw( ::com::sun::star::uno::RuntimeException )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > xForms;
+
+ FmFormPage *pFmPage = PTR_CAST( FmFormPage, GetSdrPage() );
+ if( pFmPage )
+ xForms = pFmPage->GetForms();
+
+ return xForms;
+}
+
+// XFormsSupplier2
+sal_Bool SAL_CALL SvxFmDrawPage::hasForms(void) throw( ::com::sun::star::uno::RuntimeException )
+{
+ sal_Bool bHas = sal_False;
+ FmFormPage* pFormPage = PTR_CAST( FmFormPage, GetSdrPage() );
+ if ( pFormPage )
+ bHas = pFormPage->GetForms( false ).is();
+ return bHas;
+}
+
+// ::com::sun::star::lang::XServiceInfo
+::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL SvxFmDrawPage::getSupportedServiceNames(void) throw( ::com::sun::star::uno::RuntimeException )
+{
+ return SvxDrawPage::getSupportedServiceNames();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmexch.cxx b/svx/source/form/fmexch.cxx
new file mode 100644
index 000000000000..3f52a854c850
--- /dev/null
+++ b/svx/source/form/fmexch.cxx
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmexch.hxx"
+
+#include <sot/storage.hxx>
+#include <svl/itempool.hxx>
+
+#include <dbexch.hrc>
+#include <sot/formats.hxx>
+#include <svtools/svtreebx.hxx>
+#include <tools/diagnose_ex.h>
+
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::datatransfer;
+
+ //====================================================================
+ //= OLocalExchange
+ //====================================================================
+ //--------------------------------------------------------------------
+ OLocalExchange::OLocalExchange( )
+ :m_bDragging( sal_False )
+ ,m_bClipboardOwner( sal_False )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchange::copyToClipboard( Window* _pWindow, const GrantAccess& )
+ {
+ if ( m_bClipboardOwner )
+ { // simulate a lostOwnership to notify parties interested in
+ if ( m_aClipboardListener.IsSet() )
+ m_aClipboardListener.Call( this );
+ }
+
+ m_bClipboardOwner = sal_True;
+ CopyToClipboard( _pWindow );
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchange::clear()
+ {
+ if ( isClipboardOwner() )
+ {
+ try
+ {
+ Reference< clipboard::XClipboard > xClipBoard( getOwnClipboard() );
+ if ( xClipBoard.is() )
+ xClipBoard->setContents( NULL, NULL );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ m_bClipboardOwner = sal_False;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OLocalExchange::lostOwnership( const Reference< clipboard::XClipboard >& _rxClipboard, const Reference< XTransferable >& _rxTrans ) throw(RuntimeException)
+ {
+ TransferableHelper::implCallOwnLostOwnership( _rxClipboard, _rxTrans );
+ m_bClipboardOwner = sal_False;
+
+ if ( m_aClipboardListener.IsSet() )
+ m_aClipboardListener.Call( this );
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchange::startDrag( Window* _pWindow, sal_Int8 _nDragSourceActions, const GrantAccess& )
+ {
+ m_bDragging = sal_True;
+ StartDrag( _pWindow, _nDragSourceActions );
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchange::DragFinished( sal_Int8 nDropAction )
+ {
+ TransferableHelper::DragFinished( nDropAction );
+ m_bDragging = sal_False;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool OLocalExchange::hasFormat( const DataFlavorExVector& _rFormats, sal_uInt32 _nFormatId )
+ {
+ DataFlavorExVector::const_iterator aSearch;
+
+ for ( aSearch = _rFormats.begin(); aSearch != _rFormats.end(); ++aSearch )
+ if ( aSearch->mnSotId == _nFormatId )
+ break;
+
+ return aSearch != _rFormats.end();
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool OLocalExchange::GetData( const ::com::sun::star::datatransfer::DataFlavor& /*_rFlavor*/ )
+ {
+ return sal_False; // do not have any formats by default
+ }
+
+ //====================================================================
+ //= OControlTransferData
+ //====================================================================
+ //--------------------------------------------------------------------
+ OControlTransferData::OControlTransferData( )
+ :m_pFocusEntry( NULL )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ OControlTransferData::OControlTransferData( const Reference< XTransferable >& _rxTransferable )
+ :m_pFocusEntry( NULL )
+ {
+ TransferableDataHelper aExchangedData( _rxTransferable );
+
+ // try the formats we know
+ if ( OControlExchange::hasControlPathFormat( aExchangedData.GetDataFlavorExVector() ) )
+ { // paths to the controls, relative to a root
+ Sequence< Any > aControlPathData;
+ if ( aExchangedData.GetAny( OControlExchange::getControlPathFormatId() ) >>= aControlPathData )
+ {
+ DBG_ASSERT( aControlPathData.getLength() >= 2, "OControlTransferData::OControlTransferData: invalid data for the control path format!" );
+ if ( aControlPathData.getLength() >= 2 )
+ {
+ aControlPathData[0] >>= m_xFormsRoot;
+ aControlPathData[1] >>= m_aControlPaths;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "OControlTransferData::OControlTransferData: invalid data for the control path format (2)!" );
+ }
+ }
+ if ( OControlExchange::hasHiddenControlModelsFormat( aExchangedData.GetDataFlavorExVector() ) )
+ { // sequence of models of hidden controls
+ aExchangedData.GetAny( OControlExchange::getHiddenControlModelsFormatId() ) >>= m_aHiddenControlModels;
+ }
+
+ updateFormats( );
+ }
+
+ //--------------------------------------------------------------------
+ static sal_Bool lcl_fillDataFlavorEx( SotFormatStringId nId, DataFlavorEx& _rFlavor )
+ {
+ _rFlavor.mnSotId = nId;
+ return SotExchange::GetFormatDataFlavor( _rFlavor.mnSotId, _rFlavor );
+ }
+
+ //--------------------------------------------------------------------
+ void OControlTransferData::updateFormats( )
+ {
+ m_aCurrentFormats.clear();
+ m_aCurrentFormats.reserve( 3 );
+
+ DataFlavorEx aFlavor;
+
+ if ( m_aHiddenControlModels.getLength() )
+ {
+ if ( lcl_fillDataFlavorEx( OControlExchange::getHiddenControlModelsFormatId(), aFlavor ) )
+ m_aCurrentFormats.push_back( aFlavor );
+ }
+
+ if ( m_xFormsRoot.is() && m_aControlPaths.getLength() )
+ {
+ if ( lcl_fillDataFlavorEx( OControlExchange::getControlPathFormatId(), aFlavor ) )
+ m_aCurrentFormats.push_back( aFlavor );
+ }
+
+ if ( !m_aSelectedEntries.empty() )
+ {
+ if ( lcl_fillDataFlavorEx( OControlExchange::getFieldExchangeFormatId(), aFlavor ) )
+ m_aCurrentFormats.push_back( aFlavor );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ size_t OControlTransferData::onEntryRemoved( SvLBoxEntry* _pEntry )
+ {
+ m_aSelectedEntries.erase( _pEntry );
+ return m_aSelectedEntries.size();
+ }
+
+ //--------------------------------------------------------------------
+ void OControlTransferData::addSelectedEntry( SvLBoxEntry* _pEntry )
+ {
+ m_aSelectedEntries.insert( _pEntry );
+ }
+
+ //--------------------------------------------------------------------
+ void OControlTransferData::setFocusEntry( SvLBoxEntry* _pFocusEntry )
+ {
+ m_pFocusEntry = _pFocusEntry;
+ }
+
+ //------------------------------------------------------------------------
+ void OControlTransferData::addHiddenControlsFormat(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > seqInterfaces)
+ {
+ m_aHiddenControlModels = seqInterfaces;
+ }
+
+ //------------------------------------------------------------------------
+ void OControlTransferData::buildPathFormat(SvTreeListBox* pTreeBox, SvLBoxEntry* pRoot)
+ {
+ m_aControlPaths.realloc(0);
+
+ sal_Int32 nEntryCount = m_aSelectedEntries.size();
+ if (nEntryCount == 0)
+ return;
+
+ m_aControlPaths.realloc(nEntryCount);
+ ::com::sun::star::uno::Sequence<sal_uInt32>* pAllPaths = m_aControlPaths.getArray();
+ for ( ListBoxEntrySet::const_iterator loop = m_aSelectedEntries.begin();
+ loop != m_aSelectedEntries.end();
+ ++loop, ++pAllPaths
+ )
+ {
+ // erst mal sammeln wir den Pfad in einem Array ein
+ ::std::vector< sal_uInt32 > aCurrentPath;
+ SvLBoxEntry* pCurrentEntry = *loop;
+
+ SvLBoxEntry* pLoop = pCurrentEntry;
+ while (pLoop != pRoot)
+ {
+ aCurrentPath.push_back(pLoop->GetChildListPos());
+ pLoop = pTreeBox->GetParent(pLoop);
+ DBG_ASSERT((pLoop != NULL) || (pRoot == 0), "OControlTransferData::buildPathFormat: invalid root or entry !");
+ // pLoop == NULL heisst, dass ich am oberen Ende angelangt bin, dann sollte das Ganze abbrechen, was nur bei pRoot == NULL der Fall sein wird
+ }
+
+ // dann koennen wir ihn in die ::com::sun::star::uno::Sequence uebertragen
+ Sequence<sal_uInt32>& rCurrentPath = *pAllPaths;
+ sal_Int32 nDepth = aCurrentPath.size();
+
+ rCurrentPath.realloc(nDepth);
+ sal_uInt32* pSeq = rCurrentPath.getArray();
+ sal_Int32 j,k;
+ for (j = nDepth - 1, k = 0; k<nDepth; --j, ++k)
+ pSeq[j] = aCurrentPath[k];
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void OControlTransferData::buildListFromPath(SvTreeListBox* pTreeBox, SvLBoxEntry* pRoot)
+ {
+ ListBoxEntrySet aEmpty;
+ m_aSelectedEntries.swap( aEmpty );
+
+ sal_Int32 nControls = m_aControlPaths.getLength();
+ const ::com::sun::star::uno::Sequence<sal_uInt32>* pPaths = m_aControlPaths.getConstArray();
+ for (sal_Int32 i=0; i<nControls; ++i)
+ {
+ sal_Int32 nThisPatLength = pPaths[i].getLength();
+ const sal_uInt32* pThisPath = pPaths[i].getConstArray();
+ SvLBoxEntry* pSearch = pRoot;
+ for (sal_Int32 j=0; j<nThisPatLength; ++j)
+ pSearch = pTreeBox->GetEntry(pSearch, pThisPath[j]);
+
+ m_aSelectedEntries.insert( pSearch );
+ }
+ }
+
+ //====================================================================
+ //= OControlExchange
+ //====================================================================
+ //--------------------------------------------------------------------
+ OControlExchange::OControlExchange( )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool OControlExchange::GetData( const DataFlavor& _rFlavor )
+ {
+ const sal_uInt32 nFormatId = SotExchange::GetFormat( _rFlavor );
+
+ if ( getControlPathFormatId( ) == nFormatId )
+ {
+ // ugly. We have to pack all the info into one object
+ Sequence< Any > aCompleteInfo( 2 );
+ OSL_ENSURE( m_xFormsRoot.is(), "OLocalExchange::GetData: invalid forms root for this format!" );
+ aCompleteInfo.getArray()[ 0 ] <<= m_xFormsRoot;
+ aCompleteInfo.getArray()[ 1 ] <<= m_aControlPaths;
+
+ SetAny( makeAny( aCompleteInfo ), _rFlavor );
+ }
+ else if ( getHiddenControlModelsFormatId() == nFormatId )
+ {
+ // just need to transfer the models
+ SetAny( makeAny( m_aHiddenControlModels ), _rFlavor );
+ }
+ else
+ return OLocalExchange::GetData( _rFlavor );
+
+ return sal_True;
+ }
+
+ //--------------------------------------------------------------------
+ void OControlExchange::AddSupportedFormats()
+ {
+ if (m_pFocusEntry && !m_aSelectedEntries.empty())
+ AddFormat(getFieldExchangeFormatId());
+
+ if (m_aControlPaths.getLength())
+ AddFormat(getControlPathFormatId());
+
+ if (m_aHiddenControlModels.getLength())
+ AddFormat(getHiddenControlModelsFormatId());
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt32 OControlExchange::getControlPathFormatId()
+ {
+ static sal_uInt32 s_nFormat = (sal_uInt32)-1;
+ if ((sal_uInt32)-1 == s_nFormat)
+ {
+ s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.ControlPathExchange\""));
+ DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getControlPathFormatId: bad exchange id!");
+ }
+ return s_nFormat;
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt32 OControlExchange::getHiddenControlModelsFormatId()
+ {
+ static sal_uInt32 s_nFormat = (sal_uInt32)-1;
+ if ((sal_uInt32)-1 == s_nFormat)
+ {
+ s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.HiddenControlModelsExchange\""));
+ DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getHiddenControlModelsFormatId: bad exchange id!");
+ }
+ return s_nFormat;
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt32 OControlExchange::getFieldExchangeFormatId()
+ {
+ static sal_uInt32 s_nFormat = (sal_uInt32)-1;
+ if ((sal_uInt32)-1 == s_nFormat)
+ {
+ s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.FieldNameExchange\""));
+ DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getFieldExchangeFormatId: bad exchange id!");
+ }
+ return s_nFormat;
+ }
+
+ //====================================================================
+ //= OControlExchangeHelper
+ //====================================================================
+ OLocalExchange* OControlExchangeHelper::createExchange() const
+ {
+ return new OControlExchange;
+ }
+
+ //====================================================================
+ //= OLocalExchangeHelper
+ //====================================================================
+ //--------------------------------------------------------------------
+ OLocalExchangeHelper::OLocalExchangeHelper(Window* _pDragSource)
+ :m_pDragSource(_pDragSource)
+ ,m_pTransferable(NULL)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ OLocalExchangeHelper::~OLocalExchangeHelper()
+ {
+ implReset();
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchangeHelper::startDrag( sal_Int8 nDragSourceActions )
+ {
+ DBG_ASSERT(m_pTransferable, "OLocalExchangeHelper::startDrag: not prepared!");
+ m_pTransferable->startDrag( m_pDragSource, nDragSourceActions, OLocalExchange::GrantAccess() );
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchangeHelper::copyToClipboard( ) const
+ {
+ DBG_ASSERT( m_pTransferable, "OLocalExchangeHelper::copyToClipboard: not prepared!" );
+ m_pTransferable->copyToClipboard( m_pDragSource, OLocalExchange::GrantAccess() );
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchangeHelper::implReset()
+ {
+ if (m_pTransferable)
+ {
+ m_pTransferable->setClipboardListener( Link() );
+ m_pTransferable->release();
+ m_pTransferable = NULL;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void OLocalExchangeHelper::prepareDrag( )
+ {
+ DBG_ASSERT(!m_pTransferable || !m_pTransferable->isDragging(), "OLocalExchangeHelper::prepareDrag: recursive DnD?");
+
+ implReset();
+ m_pTransferable = createExchange();
+ m_pTransferable->acquire();
+ }
+
+//........................................................................
+}
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmexpl.cxx b/svx/source/form/fmexpl.cxx
new file mode 100644
index 000000000000..59c39f21a8b8
--- /dev/null
+++ b/svx/source/form/fmexpl.cxx
@@ -0,0 +1,736 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmresids.hrc"
+#include "fmexpl.hrc"
+#include "fmexpl.hxx"
+
+#include "fmhelp.hrc"
+#include <svx/fmglob.hxx>
+#include "fmservs.hxx"
+#include <svx/fmmodel.hxx>
+#include "fmexch.hxx"
+#include "fmundo.hxx"
+#include "fmpgeimp.hxx"
+
+#include <svx/svxids.hrc>
+
+#include "fmprop.hrc"
+#include <svx/dialmgr.hxx>
+#include "svditer.hxx"
+#include <svx/svdouno.hxx>
+#include <fmundo.hxx>
+#include <svx/svdobj.hxx>
+#include <vcl/msgbox.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <vcl/menu.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/request.hxx>
+#include <tools/shl.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/sound.hxx>
+#include <svx/fmshell.hxx>
+#include "fmshimp.hxx"
+#include <svx/fmpage.hxx>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/property.hxx>
+#include <comphelper/processfactory.hxx>
+#include <osl/diagnose.h>
+#include <rtl/logfile.hxx>
+
+using namespace ::svxform;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+
+//========================================================================
+
+SV_IMPL_PTRARR_SORT( FmEntryDataArray, FmEntryDataPtr )
+SV_IMPL_PTRARR_SORT( SvLBoxEntrySortedArray, SvLBoxEntryPtr )
+
+//========================================================================
+// class FmNavInsertedHint
+//========================================================================
+TYPEINIT1( FmNavInsertedHint, SfxHint );
+DBG_NAME(FmNavInsertedHint);
+//------------------------------------------------------------------------
+FmNavInsertedHint::FmNavInsertedHint( FmEntryData* pInsertedEntryData, sal_uInt32 nRelPos )
+ :pEntryData( pInsertedEntryData )
+ ,nPos( nRelPos )
+
+{
+ DBG_CTOR(FmNavInsertedHint,NULL);
+}
+
+//------------------------------------------------------------------------
+FmNavInsertedHint::~FmNavInsertedHint()
+{
+ DBG_DTOR(FmNavInsertedHint,NULL);
+}
+
+
+//========================================================================
+// class FmNavInsertedHint
+//========================================================================
+TYPEINIT1( FmNavModelReplacedHint, SfxHint );
+DBG_NAME(FmNavModelReplacedHint);
+//------------------------------------------------------------------------
+FmNavModelReplacedHint::FmNavModelReplacedHint( FmEntryData* pAffectedEntryData )
+ :pEntryData( pAffectedEntryData )
+{
+ DBG_CTOR(FmNavModelReplacedHint,NULL);
+}
+
+//------------------------------------------------------------------------
+FmNavModelReplacedHint::~FmNavModelReplacedHint()
+{
+ DBG_DTOR(FmNavModelReplacedHint,NULL);
+}
+
+//========================================================================
+// class FmNavRemovedHint
+//========================================================================
+TYPEINIT1( FmNavRemovedHint, SfxHint );
+DBG_NAME(FmNavRemovedHint);
+//------------------------------------------------------------------------
+FmNavRemovedHint::FmNavRemovedHint( FmEntryData* pRemovedEntryData )
+ :pEntryData( pRemovedEntryData )
+{
+ DBG_CTOR(FmNavRemovedHint,NULL);
+}
+
+//------------------------------------------------------------------------
+FmNavRemovedHint::~FmNavRemovedHint()
+{
+ DBG_DTOR(FmNavRemovedHint,NULL);
+}
+
+
+//========================================================================
+// class FmNavNameChangedHint
+//========================================================================
+TYPEINIT1( FmNavNameChangedHint, SfxHint );
+DBG_NAME(FmNavNameChangedHint);
+//------------------------------------------------------------------------
+FmNavNameChangedHint::FmNavNameChangedHint( FmEntryData* pData, const ::rtl::OUString& rNewName )
+ :pEntryData( pData )
+ ,aNewName( rNewName )
+{
+ DBG_CTOR(FmNavNameChangedHint,NULL);
+}
+
+//------------------------------------------------------------------------
+FmNavNameChangedHint::~FmNavNameChangedHint()
+{
+ DBG_DTOR(FmNavNameChangedHint,NULL);
+}
+
+//========================================================================
+// class FmNavClearedHint
+//========================================================================
+TYPEINIT1( FmNavClearedHint, SfxHint );
+DBG_NAME(FmNavClearedHint);
+//------------------------------------------------------------------------
+FmNavClearedHint::FmNavClearedHint()
+{
+ DBG_CTOR(FmNavClearedHint,NULL);
+}
+
+//------------------------------------------------------------------------
+FmNavClearedHint::~FmNavClearedHint()
+{
+ DBG_DTOR(FmNavClearedHint,NULL);
+}
+
+//========================================================================
+// class FmNavRequestSelectHint
+//========================================================================
+TYPEINIT1(FmNavRequestSelectHint, SfxHint);
+
+//========================================================================
+// class FmNavViewMarksChanged
+//========================================================================
+TYPEINIT1(FmNavViewMarksChanged, SfxHint);
+
+//========================================================================
+// class FmEntryDataList
+//========================================================================
+DBG_NAME(FmEntryDataList);
+//------------------------------------------------------------------------
+FmEntryDataList::FmEntryDataList()
+{
+ DBG_CTOR(FmEntryDataList,NULL);
+}
+
+//------------------------------------------------------------------------
+FmEntryDataList::~FmEntryDataList()
+{
+ DBG_DTOR(FmEntryDataList,NULL);
+}
+
+//------------------------------------------------------------------------
+FmEntryData* FmEntryDataList::remove( FmEntryData* pItem )
+{
+ for ( FmEntryDataBaseList::iterator it = maEntryDataList.begin();
+ it < maEntryDataList.end();
+ ++it
+ )
+ {
+ if ( *it == pItem )
+ {
+ maEntryDataList.erase( it );
+ break;
+ }
+ }
+ return pItem;
+}
+
+//------------------------------------------------------------------------
+void FmEntryDataList::insert( FmEntryData* pItem, size_t Index )
+{
+ if ( Index < maEntryDataList.size() )
+ {
+ FmEntryDataBaseList::iterator it = maEntryDataList.begin();
+ ::std::advance( it, Index );
+ maEntryDataList.insert( it, pItem );
+ }
+ else
+ maEntryDataList.push_back( pItem );
+}
+
+//------------------------------------------------------------------------
+void FmEntryDataList::clear()
+{
+ for ( size_t i = 0, n = maEntryDataList.size(); i < n; ++i )
+ delete maEntryDataList[ i ];
+ maEntryDataList.clear();
+}
+
+//========================================================================
+// class FmEntryData
+//========================================================================
+TYPEINIT0( FmEntryData );
+DBG_NAME(FmEntryData);
+//------------------------------------------------------------------------
+FmEntryData::FmEntryData( FmEntryData* pParentData, const Reference< XInterface >& _rxIFace )
+ :pParent( pParentData )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmEntryData::FmEntryData" );
+ DBG_CTOR(FmEntryData,NULL);
+ pChildList = new FmEntryDataList();
+
+ newObject( _rxIFace );
+}
+
+//------------------------------------------------------------------------
+FmEntryData::~FmEntryData()
+{
+ Clear();
+ delete pChildList;
+ DBG_DTOR(FmEntryData,NULL);
+}
+
+//------------------------------------------------------------------------
+void FmEntryData::newObject( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxIFace )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmEntryData::newObject" );
+ // do not just copy, normalize it
+ m_xNormalizedIFace = Reference< XInterface >( _rxIFace, UNO_QUERY );
+ m_xProperties = m_xProperties.query( m_xNormalizedIFace );
+ m_xChild = m_xChild.query( m_xNormalizedIFace );
+}
+
+//------------------------------------------------------------------------
+FmEntryData::FmEntryData( const FmEntryData& rEntryData )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmEntryData::FmEntryData" );
+ pChildList = new FmEntryDataList();
+ aText = rEntryData.GetText();
+ m_aNormalImage = rEntryData.GetNormalImage();
+ pParent = rEntryData.GetParent();
+
+ FmEntryData* pChildData;
+ size_t nEntryCount = rEntryData.GetChildList()->size();
+ for( size_t i = 0; i < nEntryCount; i++ )
+ {
+ pChildData = rEntryData.GetChildList()->at( i );
+ FmEntryData* pNewChildData = pChildData->Clone();
+ pChildList->insert( pNewChildData, size_t(-1) );
+ }
+
+ m_xNormalizedIFace = rEntryData.m_xNormalizedIFace;
+ m_xProperties = rEntryData.m_xProperties;
+ m_xChild = rEntryData.m_xChild;
+}
+
+//------------------------------------------------------------------------
+void FmEntryData::Clear()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmEntryData::Clear" );
+ GetChildList()->clear();
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmEntryData::IsEqualWithoutChilds( FmEntryData* pEntryData )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmEntryData::IsEqualWithoutChilds" );
+ if(this == pEntryData)
+ return sal_True;
+
+ if( !pEntryData )
+ return sal_False;
+
+ if( !aText.equals(pEntryData->GetText()))
+ return sal_False;
+
+ if( !pEntryData->GetParent() && pParent )
+ return sal_False;
+
+ if( pEntryData->GetParent() && !pParent )
+ return sal_False;
+
+ if( !pEntryData->GetParent() && !pParent )
+ return sal_True;
+
+ if( !pParent->IsEqualWithoutChilds(pEntryData->GetParent()) )
+ return sal_False;
+
+ return sal_True;
+}
+
+
+//========================================================================
+// class FmFormData
+//========================================================================
+TYPEINIT1( FmFormData, FmEntryData );
+DBG_NAME(FmFormData);
+//------------------------------------------------------------------------
+FmFormData::FmFormData(
+ const Reference< XForm >& _rxForm,
+ const ImageList& _rNormalImages,
+ FmFormData* _pParent
+)
+: FmEntryData( _pParent, _rxForm ),
+ m_xForm( _rxForm )
+{
+ DBG_CTOR(FmEntryData,NULL);
+ //////////////////////////////////////////////////////////////////////
+ // Images setzen
+
+ m_aNormalImage = _rNormalImages.GetImage( RID_SVXIMG_FORM );
+
+ //////////////////////////////////////////////////////////////////////
+ // Titel setzen
+ if (m_xForm.is())
+ {
+ Reference< XPropertySet > xSet(m_xForm, UNO_QUERY);
+ if (xSet.is())
+ {
+ ::rtl::OUString aEntryName(::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME )));
+ SetText(aEntryName);
+ }
+ }
+ else
+ SetText( ::rtl::OUString() );
+}
+
+//------------------------------------------------------------------------
+FmFormData::~FmFormData()
+{
+ DBG_DTOR(FmEntryData,NULL);
+}
+
+//------------------------------------------------------------------------
+FmFormData::FmFormData( const FmFormData& rFormData )
+ :FmEntryData( rFormData )
+{
+ DBG_CTOR(FmEntryData,NULL);
+ m_xForm = rFormData.GetFormIface();
+}
+
+//------------------------------------------------------------------------
+FmEntryData* FmFormData::Clone()
+{
+ return new FmFormData( *this );
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFormData::IsEqualWithoutChilds( FmEntryData* pEntryData )
+{
+ if(this == pEntryData)
+ return sal_True;
+ if( !pEntryData->ISA(FmFormData) )
+ return sal_False;
+ FmFormData* pFormData = (FmFormData*)pEntryData;
+ if( (XForm*)m_xForm.get() != (XForm*)pFormData->GetFormIface().get() )
+ return sal_False;
+
+ return FmEntryData::IsEqualWithoutChilds( pFormData );
+}
+
+
+//========================================================================
+// class FmControlData
+//========================================================================
+TYPEINIT1( FmControlData, FmEntryData );
+DBG_NAME(FmControlData);
+//------------------------------------------------------------------------
+FmControlData::FmControlData(
+ const Reference< XFormComponent >& _rxComponent,
+ const ImageList& _rNormalImages,
+ FmFormData* _pParent
+)
+: FmEntryData( _pParent, _rxComponent ),
+ m_xFormComponent( _rxComponent )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmControlData::FmControlData" );
+ DBG_CTOR(FmControlData,NULL);
+ //////////////////////////////////////////////////////////////////////
+ // Images setzen
+ m_aNormalImage = GetImage( _rNormalImages );
+
+ //////////////////////////////////////////////////////////////////////
+ // Titel setzen
+ Reference< XPropertySet > xSet(m_xFormComponent, UNO_QUERY);
+ if( xSet.is() )
+ {
+#ifdef DBG_UTIL
+ ::rtl::OUString aEntryName = ::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME ));
+#endif
+ SetText( ::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME )));
+ }
+}
+
+//------------------------------------------------------------------------
+FmControlData::~FmControlData()
+{
+ DBG_DTOR(FmControlData,NULL);
+}
+
+//------------------------------------------------------------------------
+FmControlData::FmControlData( const FmControlData& rControlData )
+ :FmEntryData( rControlData )
+{
+ DBG_CTOR(FmControlData,NULL);
+ m_xFormComponent = rControlData.GetFormComponent();
+}
+
+//------------------------------------------------------------------------
+FmEntryData* FmControlData::Clone()
+{
+ return new FmControlData( *this );
+}
+
+//------------------------------------------------------------------------
+Image FmControlData::GetImage(const ImageList& ilNavigatorImages) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmControlData::FmControlData" );
+ //////////////////////////////////////////////////////////////////////
+ // Default-Image
+ Image aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CONTROL );
+
+ Reference< XServiceInfo > xInfo( m_xFormComponent, UNO_QUERY );
+ if (!m_xFormComponent.is())
+ return aImage;
+
+ //////////////////////////////////////////////////////////////////////
+ // Spezielle Control-Images
+ sal_Int16 nObjectType = getControlTypeByObject(xInfo);
+ switch (nObjectType)
+ {
+ case OBJ_FM_BUTTON:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_BUTTON );
+ break;
+
+ case OBJ_FM_FIXEDTEXT:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FIXEDTEXT );
+ break;
+
+ case OBJ_FM_EDIT:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_EDIT );
+ break;
+
+ case OBJ_FM_RADIOBUTTON:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_RADIOBUTTON );
+ break;
+
+ case OBJ_FM_CHECKBOX:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CHECKBOX );
+ break;
+
+ case OBJ_FM_LISTBOX:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_LISTBOX );
+ break;
+
+ case OBJ_FM_COMBOBOX:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_COMBOBOX );
+ break;
+
+ case OBJ_FM_NAVIGATIONBAR:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_NAVIGATIONBAR );
+ break;
+
+ case OBJ_FM_GROUPBOX:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_GROUPBOX );
+ break;
+
+ case OBJ_FM_IMAGEBUTTON:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_IMAGEBUTTON );
+ break;
+
+ case OBJ_FM_FILECONTROL:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FILECONTROL );
+ break;
+
+ case OBJ_FM_HIDDEN:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_HIDDEN );
+ break;
+
+ case OBJ_FM_DATEFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_DATEFIELD );
+ break;
+
+ case OBJ_FM_TIMEFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_TIMEFIELD );
+ break;
+
+ case OBJ_FM_NUMERICFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_NUMERICFIELD );
+ break;
+
+ case OBJ_FM_CURRENCYFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CURRENCYFIELD );
+ break;
+
+ case OBJ_FM_PATTERNFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_PATTERNFIELD );
+ break;
+
+ case OBJ_FM_IMAGECONTROL:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_IMAGECONTROL );
+ break;
+
+ case OBJ_FM_FORMATTEDFIELD:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FORMATTEDFIELD );
+ break;
+
+ case OBJ_FM_GRID:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_GRID );
+ break;
+
+ case OBJ_FM_SCROLLBAR:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_SCROLLBAR );
+ break;
+
+ case OBJ_FM_SPINBUTTON:
+ aImage = ilNavigatorImages.GetImage( RID_SVXIMG_SPINBUTTON);
+ break;
+ }
+
+ return aImage;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmControlData::IsEqualWithoutChilds( FmEntryData* pEntryData )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmControlData::IsEqualWithoutChilds" );
+ if(this == pEntryData)
+ return sal_True;
+
+ if( !pEntryData->ISA(FmControlData) )
+ return sal_False;
+ FmControlData* pControlData = (FmControlData*)pEntryData;
+
+ if( (XFormComponent*)m_xFormComponent.get() != (XFormComponent*)pControlData->GetFormComponent().get() )
+ return sal_False;
+
+ return FmEntryData::IsEqualWithoutChilds( pControlData );
+}
+
+//------------------------------------------------------------------------
+void FmControlData::ModelReplaced(
+ const Reference< XFormComponent >& _rxNew,
+ const ImageList& _rNormalImages
+)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmControlData::ModelReplaced" );
+ m_xFormComponent = _rxNew;
+ newObject( m_xFormComponent );
+
+ // Images neu setzen
+ m_aNormalImage = GetImage( _rNormalImages );
+}
+
+//............................................................................
+namespace svxform
+{
+//............................................................................
+
+ //========================================================================
+ // class NavigatorFrame
+ //========================================================================
+ DBG_NAME(NavigatorFrame)
+ //------------------------------------------------------------------------
+ NavigatorFrame::NavigatorFrame( SfxBindings* _pBindings, SfxChildWindow* _pMgr,
+ Window* _pParent )
+ :SfxDockingWindow( _pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) )
+ ,SfxControllerItem( SID_FM_FMEXPLORER_CONTROL, *_pBindings )
+ {
+ DBG_CTOR(NavigatorFrame,NULL);
+ SetHelpId( HID_FORM_NAVIGATOR_WIN );
+
+ m_pNavigatorTree = new NavigatorTree(comphelper::getProcessServiceFactory(), this );
+ m_pNavigatorTree->Show();
+ SetText( SVX_RES(RID_STR_FMEXPLORER) );
+ SfxDockingWindow::SetFloatingSize( Size(200,200) );
+ }
+
+ //------------------------------------------------------------------------
+ NavigatorFrame::~NavigatorFrame()
+ {
+ delete m_pNavigatorTree;
+ DBG_DTOR(NavigatorFrame,NULL);
+ }
+
+ //-----------------------------------------------------------------------
+ void NavigatorFrame::UpdateContent( FmFormShell* pFormShell )
+ {
+ m_pNavigatorTree->UpdateContent( pFormShell );
+ }
+
+ //-----------------------------------------------------------------------
+ void NavigatorFrame::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
+ {
+ if( !pState || SID_FM_FMEXPLORER_CONTROL != nSID )
+ return;
+
+ if( eState >= SFX_ITEM_AVAILABLE )
+ {
+ FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() );
+ UpdateContent( pShell );
+ }
+ else
+ UpdateContent( NULL );
+ }
+
+ //-----------------------------------------------------------------------
+ void NavigatorFrame::GetFocus()
+ {
+ if ( m_pNavigatorTree )
+ m_pNavigatorTree->GrabFocus();
+ else
+ SfxDockingWindow::GetFocus();
+ }
+
+ //-----------------------------------------------------------------------
+ sal_Bool NavigatorFrame::Close()
+ {
+ UpdateContent( NULL );
+ return SfxDockingWindow::Close();
+ }
+
+ //-----------------------------------------------------------------------
+ void NavigatorFrame::FillInfo( SfxChildWinInfo& rInfo ) const
+ {
+ SfxDockingWindow::FillInfo( rInfo );
+ rInfo.bVisible = sal_False;
+ }
+
+ //-----------------------------------------------------------------------
+ Size NavigatorFrame::CalcDockingSize( SfxChildAlignment eAlign )
+ {
+ if ( ( eAlign == SFX_ALIGN_TOP ) || ( eAlign == SFX_ALIGN_BOTTOM ) )
+ return Size();
+
+ return SfxDockingWindow::CalcDockingSize( eAlign );
+ }
+
+ //-----------------------------------------------------------------------
+ SfxChildAlignment NavigatorFrame::CheckAlignment( SfxChildAlignment _eActAlign, SfxChildAlignment _eAlign )
+ {
+ if ( ( _eAlign == SFX_ALIGN_LEFT ) || ( _eAlign == SFX_ALIGN_RIGHT ) || ( _eAlign == SFX_ALIGN_NOALIGNMENT ) )
+ return _eAlign;
+ return _eActAlign;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorFrame::Resize()
+ {
+ SfxDockingWindow::Resize();
+
+ Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT );
+ Size aLogExplSize = aLogOutputSize;
+ aLogExplSize.Width() -= 6;
+ aLogExplSize.Height() -= 6;
+
+ Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT );
+ Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT );
+
+ m_pNavigatorTree->SetPosSizePixel( aExplPos, aExplSize );
+ }
+
+
+ //========================================================================
+ // class NavigatorFrameManager
+ //========================================================================
+
+ //-----------------------------------------------------------------------
+ SFX_IMPL_DOCKINGWINDOW( NavigatorFrameManager, SID_FM_SHOW_FMEXPLORER )
+
+ //-----------------------------------------------------------------------
+ NavigatorFrameManager::NavigatorFrameManager( Window* _pParent, sal_uInt16 _nId,
+ SfxBindings* _pBindings, SfxChildWinInfo* _pInfo )
+ :SfxChildWindow( _pParent, _nId )
+ {
+ pWindow = new NavigatorFrame( _pBindings, this, _pParent );
+ eChildAlignment = SFX_ALIGN_NOALIGNMENT;
+ ((SfxDockingWindow*)pWindow)->Initialize( _pInfo );
+ }
+
+//............................................................................
+} // namespace svxform
+//............................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmexpl.src b/svx/source/form/fmexpl.src
new file mode 100644
index 000000000000..fb7ea13d9984
--- /dev/null
+++ b/svx/source/form/fmexpl.src
@@ -0,0 +1,371 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svx/svxids.hrc>
+#include "fmresids.hrc"
+#include "fmexpl.hrc"
+#include "globlmn.hrc"
+Menu RID_FMEXPLORER_POPUPMENU
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = SID_FM_NEW ;
+ HelpID = SID_FM_NEW ;
+ Text [ en-US ] = "~New" ;
+ SubMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = SID_FM_NEW_FORM ;
+ HelpID = SID_FM_NEW_FORM ;
+ Text [ en-US ] = "Form" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_NEW_HIDDEN ;
+ HelpID = SID_FM_NEW_HIDDEN ;
+ Text [ en-US ] = "Hidden Control" ;
+ };
+ };
+ };
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CHANGECONTROLTYPE ;
+ HelpID = SID_FM_CHANGECONTROLTYPE ;
+ Text [ en-US ] = "Replace with";
+ };
+ MenuItem { ITEM_EDIT_CUT };
+ MenuItem { ITEM_EDIT_COPY };
+ MenuItem { ITEM_EDIT_PASTE };
+ MenuItem
+ {
+ Identifier = SID_FM_DELETE ;
+ HelpID = SID_FM_DELETE ;
+ Text [ en-US ] = "~Delete" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_TAB_DIALOG ;
+ HelpID = SID_FM_TAB_DIALOG ;
+ Text [ en-US ] = "Tab Order..." ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_RENAME_OBJECT ;
+ HelpID = SID_FM_RENAME_OBJECT ;
+ Text [ en-US ] = "~Rename" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_SHOW_PROPERTY_BROWSER ;
+ HelpID = SID_FM_SHOW_PROPERTY_BROWSER ;
+ Text [ en-US ] = "Propert~ies" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_OPEN_READONLY ;
+ HelpID = SID_FM_OPEN_READONLY ;
+ Text [ en-US ] = "Open in Design Mode" ;
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_AUTOCONTROLFOCUS ;
+ HelpID = SID_FM_AUTOCONTROLFOCUS ;
+ Text [ en-US ] = "Automatic Control Focus";
+ };
+ };
+};
+
+Menu RID_FMSHELL_CONVERSIONMENU
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_EDIT ;
+ HelpID = SID_FM_CONVERTTO_EDIT ;
+ Command = ".uno:ConvertToEdit" ;
+ Text [ en-US ] = "~Text Box";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_BUTTON ;
+ HelpID = SID_FM_CONVERTTO_BUTTON ;
+ Command = ".uno:ConvertToButton" ;
+ Text [ en-US ] = "~Button";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_FIXEDTEXT ;
+ HelpID = SID_FM_CONVERTTO_FIXEDTEXT ;
+ Command = ".uno:ConvertToFixed" ;
+ Text [ en-US ] = "La~bel field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_GROUPBOX ;
+ HelpID = SID_FM_CONVERTTO_GROUPBOX ;
+ Command = ".uno:ConvertToGroup" ;
+ Text [ en-US ] = "G~roup Box";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_LISTBOX ;
+ HelpID = SID_FM_CONVERTTO_LISTBOX ;
+ Command = ".uno:ConvertToList" ;
+ Text [ en-US ] = "L~ist Box";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_CHECKBOX ;
+ HelpID = SID_FM_CONVERTTO_CHECKBOX ;
+ Command = ".uno:ConvertToCheckBox" ;
+ Text [ en-US ] = "~Check Box";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_RADIOBUTTON ;
+ HelpID = SID_FM_CONVERTTO_RADIOBUTTON ;
+ Command = ".uno:ConvertToRadio" ;
+ Text [ en-US ] = "~Radio Button";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_COMBOBOX ;
+ HelpID = SID_FM_CONVERTTO_COMBOBOX ;
+ Command = ".uno:ConvertToCombo" ;
+ Text [ en-US ] = "Combo Bo~x";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_IMAGEBUTTON ;
+ HelpID = SID_FM_CONVERTTO_IMAGEBUTTON ;
+ Command = ".uno:ConvertToImageBtn" ;
+ Text [ en-US ] = "I~mage Button";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_FILECONTROL ;
+ HelpID = SID_FM_CONVERTTO_FILECONTROL ;
+ Command = ".uno:ConvertToFileControl" ;
+ Text [ en-US ] = "~File Selection";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_DATE ;
+ HelpID = SID_FM_CONVERTTO_DATE ;
+ Command = ".uno:ConvertToDate" ;
+ Text [ en-US ] = "~Date Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_TIME ;
+ HelpID = SID_FM_CONVERTTO_TIME ;
+ Command = ".uno:ConvertToTime" ;
+ Text [ en-US ] = "Tim~e Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_NUMERIC ;
+ HelpID = SID_FM_CONVERTTO_NUMERIC ;
+ Command = ".uno:ConvertToNumeric" ;
+ Text [ en-US ] = "~Numerical Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_CURRENCY ;
+ HelpID = SID_FM_CONVERTTO_CURRENCY ;
+ Command = ".uno:ConvertToCurrency" ;
+ Text [ en-US ] = "C~urrency Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_PATTERN ;
+ HelpID = SID_FM_CONVERTTO_PATTERN ;
+ Command = ".uno:ConvertToPattern" ;
+ Text [ en-US ] = "~Pattern Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_IMAGECONTROL ;
+ HelpID = SID_FM_CONVERTTO_IMAGECONTROL ;
+ Command = ".uno:ConvertToImageControl" ;
+ Text [ en-US ] = "Ima~ge Control";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_FORMATTED ;
+ HelpID = SID_FM_CONVERTTO_FORMATTED ;
+ Command = ".uno:ConvertToFormatted" ;
+ Text [ en-US ] = "Fo~rmatted Field";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_SCROLLBAR ;
+ HelpID = SID_FM_CONVERTTO_SCROLLBAR ;
+ Command = ".uno:ConvertToScrollBar" ;
+ Text [ en-US ] = "Scroll bar";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_SPINBUTTON;
+ HelpID = SID_FM_CONVERTTO_SPINBUTTON;
+ Command = ".uno:ConvertToSpinButton" ;
+ Text [ en-US ] = "Spin Button";
+ };
+ MenuItem
+ {
+ Identifier = SID_FM_CONVERTTO_NAVIGATIONBAR;
+ HelpID = SID_FM_CONVERTTO_NAVIGATIONBAR;
+ Command = ".uno:ConvertToNavigationBar" ;
+ Text [ en-US ] = "Navigation Bar" ;
+ };
+ };
+};
+
+#define NAVIGATOR_IMAGEIDS \
+ IdList = \
+ { \
+ RID_SVXIMG_BUTTON ; \
+ RID_SVXIMG_RADIOBUTTON ; \
+ RID_SVXIMG_CHECKBOX ; \
+ RID_SVXIMG_FIXEDTEXT ; \
+ RID_SVXIMG_GROUPBOX ; \
+ RID_SVXIMG_EDIT ; \
+ RID_SVXIMG_LISTBOX ; \
+ RID_SVXIMG_COMBOBOX ; \
+ RID_SVXIMG_NAVIGATIONBAR ; \
+ RID_SVXIMG_CONTROL ; \
+ RID_SVXIMG_FORM ; \
+ RID_SVXIMG_FORMS ; \
+ RID_SVXIMG_COLLAPSEDNODE ; \
+ RID_SVXIMG_EXPANDEDNODE ; \
+ RID_SVXIMG_IMAGEBUTTON ; \
+ RID_SVXIMG_FILECONTROL ; \
+ RID_SVXIMG_DATEFIELD ; \
+ RID_SVXIMG_TIMEFIELD ; \
+ RID_SVXIMG_NUMERICFIELD ; \
+ RID_SVXIMG_CURRENCYFIELD ; \
+ RID_SVXIMG_PATTERNFIELD ; \
+ RID_SVXIMG_HIDDEN ; \
+ RID_SVXIMG_IMAGECONTROL ; \
+ RID_SVXIMG_GRID ; \
+ RID_SVXIMG_FILTER ; \
+ RID_SVXIMG_FORMATTEDFIELD ; \
+ RID_SVXIMG_DATE_N_TIME_FIELDS ; \
+ RID_SVXIMG_FIELD ; \
+ RID_SVXIMG_SCROLLBAR; \
+ RID_SVXIMG_SPINBUTTON; \
+ }; \
+ IdCount = 30
+
+ImageList RID_SVXIMGLIST_FMEXPL
+{
+ Prefix = "sx";
+ MaskColor = Color { Red = 0xff00 ; Green = 0x0000 ; Blue = 0xff00 ; };
+ NAVIGATOR_IMAGEIDS;
+};
+
+ModalDialog RID_SVXDLG_SETFORM
+{
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 200 , 200 ) ;
+ Moveable = TRUE ;
+ Closeable = TRUE ;
+ GroupBox GB_PATH
+ {
+ Pos = MAP_APPFONT ( 6 , 149 ) ;
+ Size = MAP_APPFONT ( 188 , 25 ) ;
+ Text [ en-US ] = "Path" ;
+ };
+ FixedText FT_PATH
+ {
+ Pos = MAP_APPFONT ( 12 , 155 ) ;
+ Size = MAP_APPFONT ( 156 , 15 ) ;
+ };
+ OKButton PB_OK
+ {
+ Pos = MAP_APPFONT ( 6 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ CancelButton PB_CANCEL
+ {
+ Pos = MAP_APPFONT ( 59 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton PB_HELP
+ {
+ Pos = MAP_APPFONT ( 123 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ Text [ en-US ] = "Select form" ;
+};
+DockingWindow RID_SVX_FMEXPLORER
+{
+ OutputSize = TRUE ;
+ SVLook = TRUE ;
+ Size = MAP_APPFONT ( 200 , 200 ) ;
+ Moveable = TRUE ;
+ Closeable = TRUE ;
+ Text [ en-US ] = "Form Navigator" ;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svx/source/form/fmitems.cxx b/svx/source/form/fmitems.cxx
new file mode 100644
index 000000000000..0b388cdb52c4
--- /dev/null
+++ b/svx/source/form/fmitems.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmitems.hxx"
+
+#include <svx/svxids.hrc>
+#include <tools/stream.hxx>
+
+//========================================================================
+// class FmInterfaceItem
+//========================================================================
+TYPEINIT1(FmInterfaceItem, SfxPoolItem);
+
+//------------------------------------------------------------------------------
+int FmInterfaceItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==(rAttr), "unequal types" );
+ return( xInterface == ((FmInterfaceItem&)rAttr).GetInterface() );
+}
+
+//------------------------------------------------------------------------------
+SfxPoolItem* FmInterfaceItem::Clone( SfxItemPool* ) const
+{
+ return new FmInterfaceItem( *this );
+}
+
+//------------------------------------------------------------------------------
+SvStream& FmInterfaceItem::Store( SvStream& rStrm , sal_uInt16 /*nItemVersion*/ ) const
+{
+ DBG_ERROR( "FmInterfaceItem::Store: not implemented!" );
+ return rStrm;
+}
+
+//------------------------------------------------------------------------------
+SfxPoolItem* FmInterfaceItem::Create( SvStream& /*rStrm*/, sal_uInt16 ) const
+{
+ DBG_ERROR( "FmInterfaceItem::Create: not implemented!" );
+ return new FmInterfaceItem( *this );
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmmodel.cxx b/svx/source/form/fmmodel.cxx
new file mode 100644
index 000000000000..751706c4509a
--- /dev/null
+++ b/svx/source/form/fmmodel.cxx
@@ -0,0 +1,372 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmundo.hxx"
+#include "fmdocumentclassification.hxx"
+#include "fmcontrollayout.hxx"
+
+#include <svx/fmmodel.hxx>
+#include <svx/fmpage.hxx>
+#include <svx/svdobj.hxx>
+#include <tools/debug.hxx>
+
+#ifndef SVX_LIGHT
+#include <sfx2/objsh.hxx>
+#else
+class SfxObjectShell;
+#endif
+
+#include <boost/optional.hpp>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::container::XNameContainer;
+using namespace svxform;
+
+TYPEINIT1(FmFormModel, SdrModel);
+
+struct FmFormModelImplData
+{
+ FmXUndoEnvironment* pUndoEnv;
+ sal_Bool bOpenInDesignIsDefaulted;
+ sal_Bool bMovingPage;
+ ::boost::optional< sal_Bool >
+ aControlsUseRefDevice;
+
+ FmFormModelImplData()
+ :pUndoEnv( NULL )
+ ,bOpenInDesignIsDefaulted( sal_True )
+ ,bMovingPage( sal_False )
+ ,aControlsUseRefDevice()
+ {
+ }
+};
+
+/*************************************************************************
+|*
+|* Ctor
+|*
+\************************************************************************/
+FmFormModel::FmFormModel(SfxItemPool* pPool, SfxObjectShell* pPers)
+ :SdrModel(pPool, pPers, LOADREFCOUNTS)
+ ,m_pImpl(NULL)
+ ,m_pObjShell(0)
+ ,m_bOpenInDesignMode(sal_False)
+ ,m_bAutoControlFocus(sal_False)
+{
+#ifndef SVX_LIGHT
+ m_pImpl = new FmFormModelImplData;
+ m_pImpl->pUndoEnv = new FmXUndoEnvironment(*this);
+ m_pImpl->pUndoEnv->acquire();
+#endif
+}
+
+/*************************************************************************
+|*
+|* Ctor
+|*
+\************************************************************************/
+FmFormModel::FmFormModel(const XubString& rPath, SfxItemPool* pPool, SfxObjectShell* pPers)
+ :SdrModel(rPath, pPool, pPers)
+ ,m_pImpl(NULL)
+ ,m_pObjShell(0)
+ ,m_bOpenInDesignMode(sal_False)
+ ,m_bAutoControlFocus(sal_False)
+{
+#ifndef SVX_LIGHT
+ m_pImpl = new FmFormModelImplData;
+ m_pImpl->pUndoEnv = new FmXUndoEnvironment(*this);
+ m_pImpl->pUndoEnv->acquire();
+#endif
+}
+
+/*************************************************************************
+|*
+|* Ctor
+|*
+\************************************************************************/
+FmFormModel::FmFormModel(SfxItemPool* pPool, SfxObjectShell* pPers,
+ bool bUseExtColorTable
+ )
+ :SdrModel(pPool, pPers, bUseExtColorTable, LOADREFCOUNTS)
+ ,m_pImpl(NULL)
+ ,m_pObjShell(0)
+ ,m_bOpenInDesignMode(sal_False)
+ ,m_bAutoControlFocus(sal_False)
+{
+#ifndef SVX_LIGHT
+ m_pImpl = new FmFormModelImplData;
+ m_pImpl->pUndoEnv = new FmXUndoEnvironment(*this);
+ m_pImpl->pUndoEnv->acquire();
+#endif
+}
+
+/*************************************************************************
+|*
+|* Ctor
+|*
+\************************************************************************/
+FmFormModel::FmFormModel(const XubString& rPath, SfxItemPool* pPool, SfxObjectShell* pPers,
+ bool bUseExtColorTable)
+ :SdrModel(rPath, pPool, pPers, bUseExtColorTable, LOADREFCOUNTS)
+ ,m_pImpl( NULL )
+ ,m_pObjShell(0)
+ ,m_bOpenInDesignMode(sal_False)
+ ,m_bAutoControlFocus(sal_False)
+{
+#ifndef SVX_LIGHT
+ m_pImpl = new FmFormModelImplData;
+ m_pImpl->pUndoEnv = new FmXUndoEnvironment(*this);
+ m_pImpl->pUndoEnv->acquire();
+#endif
+}
+
+/*************************************************************************
+|*
+|* Dtor
+|*
+\************************************************************************/
+FmFormModel::~FmFormModel()
+{
+#ifndef SVX_LIGHT
+ if (m_pObjShell && m_pImpl->pUndoEnv->IsListening(*m_pObjShell))
+ SetObjectShell(NULL);
+
+ ClearUndoBuffer();
+ // minimale grenze fuer undos
+ SetMaxUndoActionCount(1);
+
+ m_pImpl->pUndoEnv->release();
+ delete m_pImpl;
+
+#endif
+}
+
+/*************************************************************************
+|*
+|* Erzeugt eine neue Seite
+|*
+\************************************************************************/
+SdrPage* FmFormModel::AllocPage(bool bMasterPage)
+{
+ return new FmFormPage(*this, NULL, bMasterPage);
+}
+
+/*************************************************************************
+|*
+|* InsertPage
+|*
+\************************************************************************/
+void FmFormModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
+{
+#ifndef SVX_LIGHT
+ // hack solange Methode intern
+ if (m_pObjShell && !m_pImpl->pUndoEnv->IsListening( *m_pObjShell ))
+ SetObjectShell(m_pObjShell);
+#endif
+
+ SdrModel::InsertPage( pPage, nPos );
+}
+
+/*************************************************************************
+|*
+|* MovePage
+|*
+\************************************************************************/
+void FmFormModel::MovePage( USHORT nPgNum, USHORT nNewPos )
+{
+#ifndef SVX_LIGHT
+ m_pImpl->bMovingPage = sal_True;
+ // see InsertPage for this
+#endif
+
+ SdrModel::MovePage( nPgNum, nNewPos );
+
+#ifndef SVX_LIGHT
+ m_pImpl->bMovingPage = sal_False;
+#endif
+}
+
+/*************************************************************************
+|*
+|* RemovePage
+|*
+\************************************************************************/
+SdrPage* FmFormModel::RemovePage(sal_uInt16 nPgNum)
+{
+ FmFormPage* pToBeRemovedPage = dynamic_cast< FmFormPage* >( GetPage( nPgNum ) );
+ OSL_ENSURE( pToBeRemovedPage, "FmFormModel::RemovePage: *which page*?" );
+
+#ifndef SVX_LIGHT
+ if ( pToBeRemovedPage )
+ {
+ Reference< XNameContainer > xForms( pToBeRemovedPage->GetForms( false ) );
+ if ( xForms.is() )
+ m_pImpl->pUndoEnv->RemoveForms( xForms );
+ }
+#endif
+
+ FmFormPage* pRemovedPage = (FmFormPage*)SdrModel::RemovePage(nPgNum);
+ OSL_ENSURE( pRemovedPage == pToBeRemovedPage, "FmFormModel::RemovePage: inconsistency!" );
+ return pRemovedPage;
+}
+
+/*************************************************************************
+|*
+|* InsertMasterPage
+|*
+\************************************************************************/
+void FmFormModel::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos)
+{
+#ifndef SVX_LIGHT
+ // hack solange Methode intern
+ if (m_pObjShell && !m_pImpl->pUndoEnv->IsListening( *m_pObjShell ))
+ SetObjectShell(m_pObjShell);
+#endif
+
+ SdrModel::InsertMasterPage(pPage, nPos);
+}
+
+/*************************************************************************
+|*
+|* RemoveMasterPage
+|*
+\************************************************************************/
+SdrPage* FmFormModel::RemoveMasterPage(sal_uInt16 nPgNum)
+{
+ FmFormPage* pPage = (FmFormPage*)SdrModel::RemoveMasterPage(nPgNum);
+
+#ifndef SVX_LIGHT
+ if ( pPage )
+ {
+ Reference< XNameContainer > xForms( pPage->GetForms( false ) );
+ if ( xForms.is() )
+ m_pImpl->pUndoEnv->RemoveForms( xForms );
+ }
+#endif
+
+ return pPage;
+}
+
+//------------------------------------------------------------------------
+SdrLayerID FmFormModel::GetControlExportLayerId( const SdrObject& rObj ) const
+{
+ return rObj.GetLayer();
+}
+
+//------------------------------------------------------------------------
+void FmFormModel::implSetOpenInDesignMode( sal_Bool _bOpenDesignMode, sal_Bool _bForce )
+{
+ if( ( _bOpenDesignMode != m_bOpenInDesignMode ) || _bForce )
+ {
+ m_bOpenInDesignMode = _bOpenDesignMode;
+
+ if ( m_pObjShell )
+ m_pObjShell->SetModified( sal_True );
+ }
+ // no matter if we really did it or not - from now on, it does not count as defaulted anymore
+ m_pImpl->bOpenInDesignIsDefaulted = sal_False;
+}
+
+//------------------------------------------------------------------------
+void FmFormModel::SetOpenInDesignMode( sal_Bool bOpenDesignMode )
+{
+#ifndef SVX_LIGHT
+ implSetOpenInDesignMode( bOpenDesignMode, sal_False );
+#endif
+}
+
+#ifndef SVX_LIGHT
+//------------------------------------------------------------------------
+sal_Bool FmFormModel::OpenInDesignModeIsDefaulted( )
+{
+ return m_pImpl->bOpenInDesignIsDefaulted;
+}
+#endif
+
+//------------------------------------------------------------------------
+sal_Bool FmFormModel::ControlsUseRefDevice() const
+{
+ if ( !m_pImpl->aControlsUseRefDevice )
+ {
+ DocumentType eDocType = eUnknownDocumentType;
+ if ( m_pObjShell )
+ eDocType = DocumentClassification::classifyHostDocument( m_pObjShell->GetModel() );
+ m_pImpl->aControlsUseRefDevice.reset( ControlLayouter::useDocumentReferenceDevice( eDocType ) );
+ }
+ return *m_pImpl->aControlsUseRefDevice;
+}
+
+//------------------------------------------------------------------------
+void FmFormModel::SetAutoControlFocus( sal_Bool _bAutoControlFocus )
+{
+#ifndef SVX_LIGHT
+ if( _bAutoControlFocus != m_bAutoControlFocus )
+ {
+ m_bAutoControlFocus = _bAutoControlFocus;
+ m_pObjShell->SetModified( sal_True );
+ }
+#endif
+}
+
+//------------------------------------------------------------------------
+void FmFormModel::SetObjectShell( SfxObjectShell* pShell )
+{
+#ifndef SVX_LIGHT
+ if (pShell == m_pObjShell)
+ return;
+
+ if (m_pObjShell)
+ {
+ m_pImpl->pUndoEnv->EndListening( *this );
+ m_pImpl->pUndoEnv->EndListening( *m_pObjShell );
+ }
+
+ m_pObjShell = pShell;
+
+ if (m_pObjShell)
+ {
+ m_pImpl->pUndoEnv->SetReadOnly( m_pObjShell->IsReadOnly() || m_pObjShell->IsReadOnlyUI(), FmXUndoEnvironment::Accessor() );
+
+ if (!m_pImpl->pUndoEnv->IsReadOnly())
+ m_pImpl->pUndoEnv->StartListening(*this);
+
+ m_pImpl->pUndoEnv->StartListening( *m_pObjShell );
+ }
+#endif
+}
+
+//------------------------------------------------------------------------
+FmXUndoEnvironment& FmFormModel::GetUndoEnv()
+{
+ return *m_pImpl->pUndoEnv;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmobj.cxx b/svx/source/form/fmobj.cxx
new file mode 100644
index 000000000000..5f8f2e6ab526
--- /dev/null
+++ b/svx/source/form/fmobj.cxx
@@ -0,0 +1,739 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmobj.hxx"
+#include "fmprop.hrc"
+#include "fmvwimp.hxx"
+#include "fmpgeimp.hxx"
+#include "fmresids.hrc"
+#include "svx/fmview.hxx"
+#include "svx/fmglob.hxx"
+#include "svx/fmpage.hxx"
+#include "editeng/editeng.hxx"
+#include "svx/svdovirt.hxx"
+#include "svx/fmmodel.hxx"
+#include "svx/dialmgr.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+/** === end UNO includes === **/
+#include "svx/fmtools.hxx"
+
+#include <tools/shl.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/processfactory.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/resmgr.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::container;
+using namespace ::svxform;
+
+TYPEINIT1(FmFormObj, SdrUnoObj);
+DBG_NAME(FmFormObj);
+//------------------------------------------------------------------
+FmFormObj::FmFormObj(const ::rtl::OUString& rModelName,sal_Int32 _nType)
+ :SdrUnoObj ( rModelName )
+ ,m_nPos ( -1 )
+ ,m_nType ( _nType )
+ ,m_pLastKnownRefDevice ( NULL )
+{
+ DBG_CTOR(FmFormObj, NULL);
+
+ // normally, this is done in SetUnoControlModel, but if the call happened in the base class ctor,
+ // then our incarnation of it was not called (since we were not constructed at this time).
+ impl_checkRefDevice_nothrow( true );
+}
+
+//------------------------------------------------------------------
+FmFormObj::FmFormObj( sal_Int32 _nType )
+ :SdrUnoObj ( String() )
+ ,m_nPos ( -1 )
+ ,m_nType ( _nType )
+ ,m_pLastKnownRefDevice ( NULL )
+{
+ DBG_CTOR(FmFormObj, NULL);
+}
+
+//------------------------------------------------------------------
+FmFormObj::~FmFormObj()
+{
+ DBG_DTOR(FmFormObj, NULL);
+
+ Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
+ if (xHistory.is())
+ xHistory->dispose();
+
+ m_xEnvironmentHistory = NULL;
+ m_aEventsHistory.realloc(0);
+}
+
+//------------------------------------------------------------------
+void FmFormObj::SetObjEnv(const Reference< XIndexContainer > & xForm, const sal_Int32 nIdx,
+ const Sequence< ScriptEventDescriptor >& rEvts)
+{
+ m_xParent = xForm;
+ aEvts = rEvts;
+ m_nPos = nIdx;
+}
+
+//------------------------------------------------------------------
+void FmFormObj::ClearObjEnv()
+{
+ m_xParent.clear();
+ aEvts.realloc( 0 );
+ m_nPos = -1;
+}
+
+//------------------------------------------------------------------
+void FmFormObj::impl_checkRefDevice_nothrow( bool _force )
+{
+ const FmFormModel* pFormModel = PTR_CAST( FmFormModel, GetModel() );
+ if ( !pFormModel || !pFormModel->ControlsUseRefDevice() )
+ return;
+
+ OutputDevice* pCurrentRefDevice = pFormModel ? pFormModel->GetRefDevice() : NULL;
+ if ( ( m_pLastKnownRefDevice == pCurrentRefDevice ) && !_force )
+ return;
+
+ Reference< XControlModel > xControlModel( GetUnoControlModel() );
+ if ( !xControlModel.is() )
+ return;
+
+ m_pLastKnownRefDevice = pCurrentRefDevice;
+ if ( m_pLastKnownRefDevice == NULL )
+ return;
+
+ try
+ {
+ Reference< XPropertySet > xModelProps( GetUnoControlModel(), UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPropertyInfo( xModelProps->getPropertySetInfo(), UNO_SET_THROW );
+
+ static const ::rtl::OUString sRefDevicePropName( RTL_CONSTASCII_USTRINGPARAM( "ReferenceDevice" ) );
+ if ( xPropertyInfo->hasPropertyByName( sRefDevicePropName ) )
+ {
+ VCLXDevice* pUnoRefDevice = new VCLXDevice;
+ pUnoRefDevice->SetOutputDevice( m_pLastKnownRefDevice );
+ Reference< XDevice > xRefDevice( pUnoRefDevice );
+ xModelProps->setPropertyValue( sRefDevicePropName, makeAny( xRefDevice ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------
+void FmFormObj::impl_isolateControlModel_nothrow()
+{
+ try
+ {
+ Reference< XChild > xControlModel( GetUnoControlModel(), UNO_QUERY );
+ if ( xControlModel.is() )
+ {
+ Reference< XIndexContainer> xParent( xControlModel->getParent(), UNO_QUERY );
+ if ( xParent.is() )
+ {
+ sal_Int32 nPos = getElementPos( xParent.get(), xControlModel );
+ xParent->removeByIndex( nPos );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------
+void FmFormObj::SetPage(SdrPage* _pNewPage)
+{
+ if ( GetPage() == _pNewPage )
+ {
+ SdrUnoObj::SetPage(_pNewPage);
+ return;
+ }
+
+ FmFormPage* pOldFormPage = PTR_CAST( FmFormPage, GetPage() );
+ if ( pOldFormPage )
+ pOldFormPage->GetImpl().formObjectRemoved( *this );
+
+ FmFormPage* pNewFormPage = PTR_CAST( FmFormPage, _pNewPage );
+ if ( !pNewFormPage )
+ { // Maybe it makes sense to create an environment history here : if somebody set's our page to NULL, and we have a valid page before,
+ // me may want to remember our place within the old page. For this we could create a new m_xEnvironmentHistory to store it.
+ // So the next SetPage with a valid new page would restore that environment within the new page.
+ // But for the original Bug (#57300#) we don't need that, so I omit it here. Maybe this will be implemented later.
+ impl_isolateControlModel_nothrow();
+ SdrUnoObj::SetPage(_pNewPage);
+ return;
+ }
+
+ Reference< XIndexContainer > xNewPageForms( pNewFormPage->GetForms( true ), UNO_QUERY );
+ Reference< XIndexContainer > xNewParent;
+ Sequence< ScriptEventDescriptor> aNewEvents;
+
+ // calc the new parent for my model (within the new page's forms hierarchy)
+ // do we have a history ? (from :Clone)
+ if ( m_xEnvironmentHistory.is() )
+ {
+ // the element in m_xEnvironmentHistory which is equivalent to my new parent (which (perhaps) has to be created within _pNewPage->GetForms)
+ // is the right-most element in the tree.
+ Reference< XIndexContainer > xRightMostLeaf = m_xEnvironmentHistory;
+ try
+ {
+ while ( xRightMostLeaf->getCount() )
+ {
+ xRightMostLeaf.set(
+ xRightMostLeaf->getByIndex( xRightMostLeaf->getCount() - 1 ),
+ UNO_QUERY_THROW
+ );
+ }
+
+ xNewParent.set( ensureModelEnv( xRightMostLeaf, xNewPageForms ), UNO_QUERY_THROW );
+
+ // we successfully cloned the environment in m_xEnvironmentHistory, so we can use m_aEventsHistory
+ // (which describes the events of our model at the moment m_xEnvironmentHistory was created)
+ aNewEvents = m_aEventsHistory;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ if ( !xNewParent.is() )
+ {
+ // are we a valid part of our current page forms ?
+ Reference< XIndexContainer > xOldForms;
+ if ( pOldFormPage )
+ xOldForms.set( pOldFormPage->GetForms(), UNO_QUERY_THROW );
+
+ if ( xOldForms.is() )
+ {
+ // search (upward from our model) for xOldForms
+ Reference< XChild > xSearch( GetUnoControlModel(), UNO_QUERY );
+ while (xSearch.is())
+ {
+ if ( xSearch == xOldForms )
+ break;
+ xSearch = Reference< XChild >( xSearch->getParent(), UNO_QUERY );
+ }
+ if ( xSearch.is() ) // implies xSearch == xOldForms, which means we're a valid part of our current page forms hierarchy
+ {
+ Reference< XChild > xMeAsChild( GetUnoControlModel(), UNO_QUERY );
+ xNewParent.set( ensureModelEnv( xMeAsChild->getParent(), xNewPageForms ), UNO_QUERY );
+
+ if ( xNewParent.is() )
+ {
+ try
+ {
+ // transfer the events from our (model's) parent to the new (model's) parent, too
+ Reference< XEventAttacherManager > xEventManager(xMeAsChild->getParent(), UNO_QUERY);
+ Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY);
+ if (xManagerAsIndex.is())
+ {
+ sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsChild);
+ if (nPos >= 0)
+ aNewEvents = xEventManager->getScriptEvents(nPos);
+ }
+ else
+ aNewEvents = aEvts;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ }
+ }
+
+ // now set the page
+ SdrUnoObj::SetPage(_pNewPage);
+
+ // place my model within the new parent container
+ if (xNewParent.is())
+ {
+ Reference< XFormComponent > xMeAsFormComp(GetUnoControlModel(), UNO_QUERY);
+ if (xMeAsFormComp.is())
+ {
+ // check if I have another parent (and remove me, if neccessary)
+ Reference< XIndexContainer > xOldParent(xMeAsFormComp->getParent(), UNO_QUERY);
+ if (xOldParent.is())
+ {
+ sal_Int32 nPos = getElementPos(Reference< XIndexAccess > (xOldParent, UNO_QUERY), xMeAsFormComp);
+ if (nPos > -1)
+ xOldParent->removeByIndex(nPos);
+ }
+ // and insert into the new container
+ xNewParent->insertByIndex(xNewParent->getCount(), makeAny(xMeAsFormComp));
+
+ // transfer the events
+ if (aNewEvents.getLength())
+ {
+ try
+ {
+ Reference< XEventAttacherManager > xEventManager(xNewParent, UNO_QUERY);
+ Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY);
+ if (xManagerAsIndex.is())
+ {
+ sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsFormComp);
+ DBG_ASSERT(nPos >= 0, "FmFormObj::SetPage : inserted but not present ?");
+ xEventManager->registerScriptEvents(nPos, aNewEvents);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ }
+ }
+ }
+
+ // delete my history
+ Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
+ if (xHistory.is())
+ xHistory->dispose();
+
+ m_xEnvironmentHistory = NULL;
+ m_aEventsHistory.realloc(0);
+
+ if ( pNewFormPage )
+ pNewFormPage->GetImpl().formObjectInserted( *this );
+}
+
+//------------------------------------------------------------------
+sal_uInt32 FmFormObj::GetObjInventor() const
+{
+ return FmFormInventor;
+}
+
+//------------------------------------------------------------------
+sal_uInt16 FmFormObj::GetObjIdentifier() const
+{
+ return OBJ_UNO;
+}
+
+//------------------------------------------------------------------
+void FmFormObj::clonedFrom(const FmFormObj* _pSource)
+{
+ DBG_ASSERT(_pSource != NULL, "FmFormObj::clonedFrom : invalid source !");
+ Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
+ if (xHistory.is())
+ xHistory->dispose();
+
+ m_xEnvironmentHistory = NULL;
+ m_aEventsHistory.realloc(0);
+
+ Reference< XChild > xSourceAsChild(_pSource->GetUnoControlModel(), UNO_QUERY);
+ if (!xSourceAsChild.is())
+ return;
+
+ Reference< XInterface > xSourceContainer = xSourceAsChild->getParent();
+
+ m_xEnvironmentHistory = Reference< XIndexContainer >(
+ ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.Forms")) ),
+ UNO_QUERY);
+ DBG_ASSERT(m_xEnvironmentHistory.is(), "FmFormObj::clonedFrom : could not create a forms collection !");
+
+ if (m_xEnvironmentHistory.is())
+ {
+ ensureModelEnv(xSourceContainer, m_xEnvironmentHistory);
+ m_aEventsHistory = aEvts;
+ // if we we're clone there was a call to operator=, so aEvts are excatly the events we need here ...
+ }
+}
+
+//------------------------------------------------------------------
+SdrObject* FmFormObj::Clone() const
+{
+ SdrObject* pReturn = SdrUnoObj::Clone();
+
+ FmFormObj* pFormObject = PTR_CAST(FmFormObj, pReturn);
+ DBG_ASSERT(pFormObject != NULL, "FmFormObj::Clone : invalid clone !");
+ if (pFormObject)
+ pFormObject->clonedFrom(this);
+
+ return pReturn;
+}
+
+//------------------------------------------------------------------
+void FmFormObj::NbcReformatText()
+{
+ impl_checkRefDevice_nothrow( false );
+ SdrUnoObj::NbcReformatText();
+}
+
+//------------------------------------------------------------------
+void FmFormObj::operator= (const SdrObject& rObj)
+{
+ SdrUnoObj::operator= (rObj);
+
+ FmFormObj* pFormObj = PTR_CAST(FmFormObj, &rObj);
+ if (pFormObj)
+ {
+ // liegt das UnoControlModel in einer Eventumgebung,
+ // dann koennen noch Events zugeordnet sein
+ Reference< XFormComponent > xContent(pFormObj->xUnoControlModel, UNO_QUERY);
+ if (xContent.is())
+ {
+ Reference< XEventAttacherManager > xManager(xContent->getParent(), UNO_QUERY);
+ Reference< XIndexAccess > xManagerAsIndex(xManager, UNO_QUERY);
+ if (xManagerAsIndex.is())
+ {
+ sal_Int32 nPos = getElementPos( xManagerAsIndex, xContent );
+ if ( nPos >= 0 )
+ aEvts = xManager->getScriptEvents( nPos );
+ }
+ }
+ else
+ aEvts = pFormObj->aEvts;
+ }
+}
+
+//------------------------------------------------------------------
+namespace
+{
+ String lcl_getFormComponentAccessPath(const Reference< XInterface >& _xElement, Reference< XInterface >& _rTopLevelElement)
+ {
+ Reference< ::com::sun::star::form::XFormComponent> xChild(_xElement, UNO_QUERY);
+ Reference< ::com::sun::star::container::XIndexAccess> xParent;
+ if (xChild.is())
+ xParent = Reference< ::com::sun::star::container::XIndexAccess>(xChild->getParent(), UNO_QUERY);
+
+ // while the current content is a form
+ String sReturn;
+ String sCurrentIndex;
+ while (xChild.is())
+ {
+ // get the content's relative pos within it's parent container
+ sal_Int32 nPos = getElementPos(xParent, xChild);
+
+ // prepend this current relaive pos
+ sCurrentIndex = String::CreateFromInt32(nPos);
+ if (sReturn.Len() != 0)
+ {
+ sCurrentIndex += '\\';
+ sCurrentIndex += sReturn;
+ }
+
+ sReturn = sCurrentIndex;
+
+ // travel up
+ if (::comphelper::query_interface((Reference< XInterface >)xParent,xChild))
+ xParent = Reference< ::com::sun::star::container::XIndexAccess>(xChild->getParent(), UNO_QUERY);
+ }
+
+ _rTopLevelElement = xParent;
+ return sReturn;
+ }
+}
+
+//------------------------------------------------------------------
+Reference< XInterface > FmFormObj::ensureModelEnv(const Reference< XInterface > & _rSourceContainer, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > _rTopLevelDestContainer)
+{
+ Reference< XInterface > xTopLevelSouce;
+ String sAccessPath = lcl_getFormComponentAccessPath(_rSourceContainer, xTopLevelSouce);
+ if (!xTopLevelSouce.is())
+ // somthing went wrong, maybe _rSourceContainer isn't part of a valid forms hierarchy
+ return Reference< XInterface > ();
+
+ Reference< XIndexContainer > xDestContainer(_rTopLevelDestContainer);
+ Reference< XIndexContainer > xSourceContainer(xTopLevelSouce, UNO_QUERY);
+ DBG_ASSERT(xSourceContainer.is(), "FmFormObj::ensureModelEnv : the top level source is invalid !");
+
+ for (xub_StrLen i=0; i<sAccessPath.GetTokenCount('\\'); ++i)
+ {
+ sal_uInt16 nIndex = (sal_uInt16)sAccessPath.GetToken(i, '\\').ToInt32();
+
+ // get the DSS of the source form (we have to find an aquivalent for)
+ DBG_ASSERT(nIndex<xSourceContainer->getCount(), "FmFormObj::ensureModelEnv : invalid access path !");
+ Reference< XPropertySet > xSourceForm;
+ xSourceContainer->getByIndex(nIndex) >>= xSourceForm;
+ DBG_ASSERT(xSourceForm.is(), "FmFormObj::ensureModelEnv : invalid source form !");
+
+ Any aSrcCursorSource, aSrcCursorSourceType, aSrcDataSource;
+ DBG_ASSERT(::comphelper::hasProperty(FM_PROP_COMMAND, xSourceForm) && ::comphelper::hasProperty(FM_PROP_COMMANDTYPE, xSourceForm)
+ && ::comphelper::hasProperty(FM_PROP_DATASOURCE, xSourceForm), "FmFormObj::ensureModelEnv : invalid access path or invalid form (missing props) !");
+ // the parent access path should refer to a row set
+ try
+ {
+ aSrcCursorSource = xSourceForm->getPropertyValue(FM_PROP_COMMAND);
+ aSrcCursorSourceType = xSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE);
+ aSrcDataSource = xSourceForm->getPropertyValue(FM_PROP_DATASOURCE);
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmFormObj::ensureModelEnv : could not retrieve a source DSS !");
+ }
+
+
+ // calc the number of (source) form siblings with the same DSS
+ Reference< XPropertySet > xCurrentSourceForm, xCurrentDestForm;
+ sal_Int16 nCurrentSourceIndex = 0, nCurrentDestIndex = 0;
+ while (nCurrentSourceIndex <= nIndex)
+ {
+ sal_Bool bEqualDSS = sal_False;
+ while (!bEqualDSS) // (we don't have to check nCurrentSourceIndex here : it's bound by nIndex)
+ {
+ xSourceContainer->getByIndex(nCurrentSourceIndex) >>= xCurrentSourceForm;
+ DBG_ASSERT(xCurrentSourceForm.is(), "FmFormObj::ensureModelEnv : invalid form ancestor (2) !");
+ bEqualDSS = sal_False;
+ if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentSourceForm))
+ { // it is a form
+ try
+ {
+ if ( ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_COMMAND), aSrcCursorSource)
+ && ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE), aSrcCursorSourceType)
+ && ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_DATASOURCE), aSrcDataSource)
+ )
+ {
+ bEqualDSS = sal_True;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmFormObj::ensureModelEnv : exception while getting a sibling's DSS !");
+ }
+
+ }
+ ++nCurrentSourceIndex;
+ }
+
+ DBG_ASSERT(bEqualDSS, "FmFormObj::ensureModelEnv : found no source form !");
+ // ??? at least the nIndex-th one should have been found ???
+
+ // now search the next one with the given DSS (within the destination container)
+ bEqualDSS = sal_False;
+ while (!bEqualDSS && (nCurrentDestIndex < xDestContainer->getCount()))
+ {
+ xDestContainer->getByIndex(nCurrentDestIndex) >>= xCurrentDestForm;
+ DBG_ASSERT(xCurrentDestForm.is(), "FmFormObj::ensureModelEnv : invalid destination form !");
+ bEqualDSS = sal_False;
+ if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentDestForm))
+ { // it is a form
+ try
+ {
+ if ( ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_COMMAND), aSrcCursorSource)
+ && ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_COMMANDTYPE), aSrcCursorSourceType)
+ && ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_DATASOURCE), aSrcDataSource)
+ )
+ {
+ bEqualDSS = sal_True;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmFormObj::ensureModelEnv : exception while getting a destination DSS !");
+ }
+
+ }
+ ++nCurrentDestIndex;
+ }
+
+ if (!bEqualDSS)
+ { // There is at least one more source form with the given DSS than destination forms are.
+ // correct this ...
+ try
+ {
+ // create and insert (into the destination) a copy of the form
+ xCurrentDestForm.set(
+ ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.component.DataForm" )) ),
+ UNO_QUERY_THROW );
+ ::comphelper::copyProperties( xCurrentSourceForm, xCurrentDestForm );
+
+ DBG_ASSERT(nCurrentDestIndex == xDestContainer->getCount(), "FmFormObj::ensureModelEnv : something went wrong with the numbers !");
+ xDestContainer->insertByIndex(nCurrentDestIndex, makeAny(xCurrentDestForm));
+
+ ++nCurrentDestIndex;
+ // like nCurrentSourceIndex, nCurrentDestIndex now points 'behind' the form it actally means
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmFormObj::ensureModelEnv : something went seriously wrong while creating a new form !");
+ // no more options anymore ...
+ return Reference< XInterface > ();
+ }
+
+ }
+ }
+
+ // now xCurrentDestForm is a form equivalent to xSourceForm (which means they have the same DSS and the same number
+ // of left siblings with the same DSS, which counts for all their ancestors, too)
+
+ // go down
+ xDestContainer = Reference< XIndexContainer > (xCurrentDestForm, UNO_QUERY);
+ xSourceContainer = Reference< XIndexContainer > (xSourceForm, UNO_QUERY);
+ DBG_ASSERT(xDestContainer.is() && xSourceContainer.is(), "FmFormObj::ensureModelEnv : invalid container !");
+ }
+
+ return Reference< XInterface > (xDestContainer, UNO_QUERY);
+}
+
+//------------------------------------------------------------------
+void FmFormObj::SetModel( SdrModel* _pNewModel )
+{
+ SdrUnoObj::SetModel( _pNewModel );
+ impl_checkRefDevice_nothrow();
+}
+
+//------------------------------------------------------------------
+FmFormObj* FmFormObj::GetFormObject( SdrObject* _pSdrObject )
+{
+ FmFormObj* pFormObject = dynamic_cast< FmFormObj* >( _pSdrObject );
+ if ( !pFormObject )
+ {
+ SdrVirtObj* pVirtualObject = dynamic_cast< SdrVirtObj* >( _pSdrObject );
+ if ( pVirtualObject )
+ pFormObject = dynamic_cast< FmFormObj* >( &pVirtualObject->ReferencedObj() );
+ }
+ return pFormObject;
+}
+
+//------------------------------------------------------------------
+const FmFormObj* FmFormObj::GetFormObject( const SdrObject* _pSdrObject )
+{
+ const FmFormObj* pFormObject = dynamic_cast< const FmFormObj* >( _pSdrObject );
+ if ( !pFormObject )
+ {
+ const SdrVirtObj* pVirtualObject = dynamic_cast< const SdrVirtObj* >( _pSdrObject );
+ if ( pVirtualObject )
+ pFormObject = dynamic_cast< const FmFormObj* >( &pVirtualObject->GetReferencedObj() );
+ }
+ return pFormObject;
+}
+
+//------------------------------------------------------------------
+void FmFormObj::SetUnoControlModel( const Reference< com::sun::star::awt::XControlModel >& _rxModel )
+{
+ SdrUnoObj::SetUnoControlModel( _rxModel );
+
+ // TODO: call something like formObjectInserted at the form page, to tell it the new model
+
+ impl_checkRefDevice_nothrow( true );
+}
+
+//------------------------------------------------------------------
+bool FmFormObj::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd )
+{
+ bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
+ if ( bResult && SDRCREATE_FORCEEND == eCmd && rStat.GetView() )
+ {
+ if ( pPage )
+ {
+ FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pPage );
+
+ try
+ {
+ Reference< XFormComponent > xContent( xUnoControlModel, UNO_QUERY_THROW );
+ Reference< XForm > xParentForm( xContent->getParent(), UNO_QUERY );
+
+ Reference< XIndexContainer > xFormToInsertInto;
+
+ if ( !xParentForm.is() )
+ { // model is not yet part of a form component hierachy
+ xParentForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
+ xFormToInsertInto.set( xParentForm, UNO_QUERY_THROW );
+ }
+
+ rPage.GetImpl().setUniqueName( xContent, xParentForm );
+
+ if ( xFormToInsertInto.is() )
+ xFormToInsertInto->insertByIndex( xFormToInsertInto->getCount(), makeAny( xContent ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ FmFormView* pView( dynamic_cast< FmFormView* >( rStat.GetView() ) );
+ FmXFormView* pViewImpl = pView ? pView->GetImpl() : NULL;
+ OSL_ENSURE( pViewImpl, "FmFormObj::EndCreate: no view!?" );
+ if ( pViewImpl )
+ pViewImpl->onCreatedFormObject( *this );
+ }
+ return bResult;
+}
+
+//------------------------------------------------------------------------------
+void FmFormObj::BrkCreate( SdrDragStat& rStat )
+{
+ SdrUnoObj::BrkCreate( rStat );
+ impl_isolateControlModel_nothrow();
+}
+
+// -----------------------------------------------------------------------------
+sal_Int32 FmFormObj::getType() const
+{
+ return m_nType;
+}
+
+// -----------------------------------------------------------------------------
+// #i70852# overload Layer interface to force to FormColtrol layer
+
+SdrLayerID FmFormObj::GetLayer() const
+{
+ // #i72535#
+ // i70852 was too radical, in SW obects (and thus, FormControls, too)
+ // get moved to invisible layers to hide them (e.g. in hidden sections).
+ // This means that form controls ARE allowed to be on other layers than
+ // the form control layer ATM and that being member of form control layer
+ // is no criteria to find all FormControls of a document.
+ // To fix, use parent functionality
+ return SdrUnoObj::GetLayer();
+}
+
+void FmFormObj::NbcSetLayer(SdrLayerID nLayer)
+{
+ // #i72535#
+ // See above. To fix, use parent functionality
+ return SdrUnoObj::NbcSetLayer(nLayer);
+}
+
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmobjfac.cxx b/svx/source/form/fmobjfac.cxx
new file mode 100644
index 000000000000..7d71331acf00
--- /dev/null
+++ b/svx/source/form/fmobjfac.cxx
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <comphelper/stl_types.hxx>
+#include <svx/svdobj.hxx>
+#include "svx/fmtools.hxx"
+#include "fmservs.hxx"
+
+#include "fmobjfac.hxx"
+
+#include <svx/fmglob.hxx>
+
+#include "fmobj.hxx"
+#include "fmshimp.hxx"
+
+#include <svx/fmshell.hxx>
+
+#include <svx/svxids.hrc>
+#include "tbxform.hxx"
+#include <tools/resid.hxx>
+
+#include "fmresids.hrc"
+#include <tools/shl.hxx>
+#include <svx/dialmgr.hxx>
+#include "fmservs.hxx"
+#include "tabwin.hxx"
+#include "fmexpl.hxx"
+#include "filtnav.hxx"
+
+#include "fmprop.hrc"
+#include "fmPropBrw.hxx"
+#include "datanavi.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::svxform;
+
+static BOOL bInit = FALSE;
+
+/*************************************************************************
+|*
+|* Ctor
+|*
+\************************************************************************/
+FmFormObjFactory::FmFormObjFactory()
+{
+ if ( !bInit )
+ {
+ SdrObjFactory::InsertMakeObjectHdl(LINK(this, FmFormObjFactory, MakeObject));
+
+ //////////////////////////////////////////////////////////////////////
+ // Konfigurations-::com::sun::star::frame::Controller und NavigationBar registrieren
+ SvxFmTbxCtlConfig::RegisterControl( SID_FM_CONFIG );
+ SvxFmTbxCtlAbsRec::RegisterControl( SID_FM_RECORD_ABSOLUTE );
+ SvxFmTbxCtlRecText::RegisterControl( SID_FM_RECORD_TEXT );
+ SvxFmTbxCtlRecFromText::RegisterControl( SID_FM_RECORD_FROM_TEXT );
+ SvxFmTbxCtlRecTotal::RegisterControl( SID_FM_RECORD_TOTAL );
+ SvxFmTbxPrevRec::RegisterControl( SID_FM_RECORD_PREV );
+ SvxFmTbxNextRec::RegisterControl( SID_FM_RECORD_NEXT );
+ ControlConversionMenuController::RegisterControl(SID_FM_CHANGECONTROLTYPE);
+
+ // Registrieung von globalen fenstern
+ FmFieldWinMgr::RegisterChildWindow();
+ FmPropBrwMgr::RegisterChildWindow();
+ NavigatorFrameManager::RegisterChildWindow();
+ DataNavigatorManager::RegisterChildWindow();
+ FmFilterNavigatorWinMgr::RegisterChildWindow();
+
+ //////////////////////////////////////////////////////////////////////
+ // Interface fuer die Formshell registrieren
+ FmFormShell::RegisterInterface(0);
+
+ ImplSmartRegisterUnoServices();
+ bInit = TRUE;
+ }
+}
+
+
+/*************************************************************************
+|*
+|* Dtor
+|*
+\************************************************************************/
+FmFormObjFactory::~FmFormObjFactory()
+{
+}
+
+
+/*************************************************************************
+|*
+|* ::com::sun::star::form::Form-Objekte erzeugen
+|*
+\************************************************************************/
+namespace
+{
+ void lcl_initProperty( FmFormObj* _pObject, const ::rtl::OUString& _rPropName, const Any& _rValue )
+ {
+ try
+ {
+ Reference< XPropertySet > xModelSet( _pObject->GetUnoControlModel(), UNO_QUERY );
+ if ( xModelSet.is() )
+ xModelSet->setPropertyValue( _rPropName, _rValue );
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "lcl_initProperty: caught an exception!" );
+ }
+ }
+}
+
+IMPL_LINK(FmFormObjFactory, MakeObject, SdrObjFactory*, pObjFactory)
+{
+ if (pObjFactory->nInventor == FmFormInventor)
+ {
+ ::rtl::OUString sServiceSpecifier;
+
+ typedef ::std::vector< ::std::pair< ::rtl::OUString, Any > > PropertyValueArray;
+ PropertyValueArray aInitialProperties;
+
+ switch ( pObjFactory->nIdentifier )
+ {
+ case OBJ_FM_EDIT:
+ sServiceSpecifier = FM_COMPONENT_EDIT;
+ break;
+
+ case OBJ_FM_BUTTON:
+ sServiceSpecifier = FM_COMPONENT_COMMANDBUTTON;
+ break;
+
+ case OBJ_FM_FIXEDTEXT:
+ sServiceSpecifier = FM_COMPONENT_FIXEDTEXT;
+ break;
+
+ case OBJ_FM_LISTBOX:
+ sServiceSpecifier = FM_COMPONENT_LISTBOX;
+ break;
+
+ case OBJ_FM_CHECKBOX:
+ sServiceSpecifier = FM_COMPONENT_CHECKBOX;
+ break;
+
+ case OBJ_FM_RADIOBUTTON:
+ sServiceSpecifier = FM_COMPONENT_RADIOBUTTON;
+ break;
+
+ case OBJ_FM_GROUPBOX:
+ sServiceSpecifier = FM_COMPONENT_GROUPBOX;
+ break;
+
+ case OBJ_FM_COMBOBOX:
+ sServiceSpecifier = FM_COMPONENT_COMBOBOX;
+ break;
+
+ case OBJ_FM_GRID:
+ sServiceSpecifier = FM_COMPONENT_GRID;
+ break;
+
+ case OBJ_FM_IMAGEBUTTON:
+ sServiceSpecifier = FM_COMPONENT_IMAGEBUTTON;
+ break;
+
+ case OBJ_FM_FILECONTROL:
+ sServiceSpecifier = FM_COMPONENT_FILECONTROL;
+ break;
+
+ case OBJ_FM_DATEFIELD:
+ sServiceSpecifier = FM_COMPONENT_DATEFIELD;
+ break;
+
+ case OBJ_FM_TIMEFIELD:
+ sServiceSpecifier = FM_COMPONENT_TIMEFIELD;
+ aInitialProperties.push_back( PropertyValueArray::value_type( FM_PROP_TIMEMAX, makeAny( (sal_Int32)( Time( 23, 59, 59, 99 ).GetTime() ) ) ) );
+ break;
+
+ case OBJ_FM_NUMERICFIELD:
+ sServiceSpecifier = FM_COMPONENT_NUMERICFIELD;
+ break;
+
+ case OBJ_FM_CURRENCYFIELD:
+ sServiceSpecifier = FM_COMPONENT_CURRENCYFIELD;
+ break;
+
+ case OBJ_FM_PATTERNFIELD:
+ sServiceSpecifier = FM_COMPONENT_PATTERNFIELD;
+ break;
+
+ case OBJ_FM_HIDDEN:
+ sServiceSpecifier = FM_COMPONENT_HIDDEN;
+ break;
+
+ case OBJ_FM_IMAGECONTROL:
+ sServiceSpecifier = FM_COMPONENT_IMAGECONTROL;
+ break;
+
+ case OBJ_FM_FORMATTEDFIELD:
+ sServiceSpecifier = FM_COMPONENT_FORMATTEDFIELD;
+ break;
+
+ case OBJ_FM_NAVIGATIONBAR:
+ sServiceSpecifier = FM_SUN_COMPONENT_NAVIGATIONBAR;
+ break;
+
+ case OBJ_FM_SCROLLBAR:
+ sServiceSpecifier = FM_SUN_COMPONENT_SCROLLBAR;
+ aInitialProperties.push_back( PropertyValueArray::value_type( FM_PROP_BORDER, makeAny( (sal_Int16)0 ) ) );
+ break;
+
+ case OBJ_FM_SPINBUTTON:
+ sServiceSpecifier = FM_SUN_COMPONENT_SPINBUTTON;
+ aInitialProperties.push_back( PropertyValueArray::value_type( FM_PROP_BORDER, makeAny( (sal_Int16)0 ) ) );
+ break;
+ }
+
+ // create the actual object
+ if ( sServiceSpecifier.getLength() )
+ pObjFactory->pNewObj = new FmFormObj( sServiceSpecifier, pObjFactory->nIdentifier );
+ else
+ pObjFactory->pNewObj = new FmFormObj( pObjFactory->nIdentifier );
+
+ // initialize some properties which we want to differ from the defaults
+ for ( PropertyValueArray::const_iterator aInitProp = aInitialProperties.begin();
+ aInitProp != aInitialProperties.end();
+ ++aInitProp
+ )
+ {
+ lcl_initProperty(
+ static_cast< FmFormObj* >( pObjFactory->pNewObj ),
+ aInitProp->first,
+ aInitProp->second
+ );
+ }
+ }
+
+ return 0;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmpage.cxx b/svx/source/form/fmpage.cxx
new file mode 100644
index 000000000000..ddcf5a445926
--- /dev/null
+++ b/svx/source/form/fmpage.cxx
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <sal/macros.h>
+
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+#include <svx/fmpage.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+
+
+#include <svx/fmmodel.hxx>
+
+#ifndef SVX_LIGHT
+#include "fmobj.hxx"
+#endif
+
+#ifndef SVX_LIGHT
+#include "fmresids.hrc"
+#endif
+#include <tools/shl.hxx>
+#include <svx/dialmgr.hxx>
+
+#ifndef SVX_LIGHT
+#include "fmpgeimp.hxx"
+#endif
+
+#ifndef SVX_LIGHT
+#include <sfx2/objsh.hxx>
+#endif
+#include "svditer.hxx"
+#include <svx/svdview.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/help.hxx>
+
+
+#ifndef SVX_LIGHT
+#include <svx/fmglob.hxx>
+#include "fmprop.hrc"
+#include "fmundo.hxx"
+#include "svx/fmtools.hxx"
+using namespace ::svxform;
+#endif
+#include <comphelper/property.hxx>
+#include <rtl/logfile.hxx>
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::container::XChild;
+using com::sun::star::container::XNameContainer;
+
+TYPEINIT1(FmFormPage, SdrPage);
+
+//------------------------------------------------------------------
+FmFormPage::FmFormPage(FmFormModel& rModel, StarBASIC* _pBasic, bool bMasterPage)
+ :SdrPage(rModel, bMasterPage)
+#ifndef SVX_LIGHT
+ ,m_pImpl( new FmFormPageImpl( *this ) )
+#else
+ ,m_pImpl(NULL)
+#endif
+ ,m_pBasic(_pBasic)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::FmFormPage" );
+}
+
+//------------------------------------------------------------------
+FmFormPage::FmFormPage(const FmFormPage& rPage)
+ :SdrPage(rPage)
+#ifndef SVX_LIGHT
+ ,m_pImpl(new FmFormPageImpl( *this, rPage.GetImpl() ) )
+#else
+ ,m_pImpl(NULL)
+#endif
+ ,m_pBasic(0)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::FmFormPage" );
+ m_sPageName = rPage.m_sPageName;
+}
+
+//------------------------------------------------------------------
+FmFormPage::~FmFormPage()
+{
+#ifndef SVX_LIGHT
+ delete m_pImpl;
+#endif
+}
+
+//------------------------------------------------------------------
+void FmFormPage::SetModel(SdrModel* pNewModel)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::SetModel" );
+ /* #35055# */
+ // we want to call the super's "SetModel" method even if the model is the
+ // same, in case code somewhere in the system depends on it. But our code
+ // doesn't, so get the old model to do a check.
+ SdrModel *pOldModel = GetModel();
+
+ SdrPage::SetModel( pNewModel );
+
+ /* #35055# */
+ if ( ( pOldModel != pNewModel ) && m_pImpl )
+ {
+ try
+ {
+ Reference< XNameContainer > xForms( m_pImpl->getForms( false ) );
+ if ( xForms.is() )
+ {
+ // we want to keep the current collection, just reset the model
+ // with which it's associated.
+ Reference< XChild > xAsChild( xForms, UNO_QUERY );
+ if ( xAsChild.is() )
+ {
+ FmFormModel* pDrawModel = (FmFormModel*) GetModel();
+ SfxObjectShell* pObjShell = pDrawModel->GetObjectShell();
+ if ( pObjShell )
+ xAsChild->setParent( pObjShell->GetModel() );
+ }
+ }
+ }
+ catch( ::com::sun::star::uno::Exception const& )
+ {
+ OSL_ENSURE( sal_False, "UNO Exception caught resetting model for m_pImpl (FmFormPageImpl) in FmFormPage::SetModel" );
+ }
+ }
+}
+
+//------------------------------------------------------------------
+SdrPage* FmFormPage::Clone() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::Clone" );
+ return new FmFormPage(*this);
+ // hier fehlt noch ein kopieren der Objekte
+}
+
+//------------------------------------------------------------------
+void FmFormPage::InsertObject(SdrObject* pObj, ULONG nPos,
+ const SdrInsertReason* pReason)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::InsertObject" );
+ SdrPage::InsertObject( pObj, nPos, pReason );
+#ifndef SVX_LIGHT
+ if (GetModel() && (!pReason || pReason->GetReason() != SDRREASON_STREAMING))
+ ((FmFormModel*)GetModel())->GetUndoEnv().Inserted(pObj);
+#endif
+}
+
+//------------------------------------------------------------------
+const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > & FmFormPage::GetForms( bool _bForceCreate ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::GetForms" );
+#ifndef SVX_LIGHT
+ const SdrPage& rMasterPage( *this );
+ const FmFormPage* pFormPage = dynamic_cast< const FmFormPage* >( &rMasterPage );
+ OSL_ENSURE( pFormPage, "FmFormPage::GetForms: referenced page is no FmFormPage - is this allowed?!" );
+ if ( !pFormPage )
+ pFormPage = this;
+
+ return pFormPage->m_pImpl->getForms( _bForceCreate );
+#else
+ static ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > aRef;
+ return aRef;
+#endif
+}
+
+//------------------------------------------------------------------
+sal_Bool FmFormPage::RequestHelp( Window* pWindow, SdrView* pView,
+ const HelpEvent& rEvt )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::RequestHelp" );
+#ifndef SVX_LIGHT
+ if( pView->IsAction() )
+ return sal_False;
+
+ Point aPos = rEvt.GetMousePosPixel();
+ aPos = pWindow->ScreenToOutputPixel( aPos );
+ aPos = pWindow->PixelToLogic( aPos );
+
+ SdrObject* pObj = NULL;
+ SdrPageView* pPV = NULL;
+ if ( !pView->PickObj( aPos, 0, pObj, pPV, SDRSEARCH_DEEP ) )
+ return sal_False;
+
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
+ if ( !pFormObject )
+ return sal_False;
+
+ UniString aHelpText;
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet( pFormObject->GetUnoControlModel(), ::com::sun::star::uno::UNO_QUERY );
+ if (xSet.is())
+ {
+ if (::comphelper::hasProperty(FM_PROP_HELPTEXT, xSet))
+ aHelpText = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_HELPTEXT)).getStr();
+
+ if (!aHelpText.Len() && ::comphelper::hasProperty(FM_PROP_TARGET_URL, xSet))
+ {
+ ::rtl::OUString aText = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_TARGET_URL));
+ INetURLObject aUrl(aText);
+
+ // testen, ob es ein Protokoll-Typ ist, den ich anzeigen will
+ INetProtocol aProtocol = aUrl.GetProtocol();
+ static const INetProtocol s_aQuickHelpSupported[] =
+ { INET_PROT_FTP, INET_PROT_HTTP, INET_PROT_FILE, INET_PROT_MAILTO, INET_PROT_NEWS,
+ INET_PROT_HTTPS, INET_PROT_JAVASCRIPT, INET_PROT_IMAP, INET_PROT_POP3,
+ INET_PROT_VIM, INET_PROT_LDAP
+ };
+ for (sal_uInt16 i=0; i < SAL_N_ELEMENTS(s_aQuickHelpSupported); ++i)
+ if (s_aQuickHelpSupported[i] == aProtocol)
+ {
+ aHelpText = INetURLObject::decode(aUrl.GetURLNoPass(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
+ break;
+ }
+ }
+ }
+ if ( aHelpText.Len() != 0 )
+ {
+ // Hilfe anzeigen
+ Rectangle aItemRect = pObj->GetCurrentBoundRect();
+ aItemRect = pWindow->LogicToPixel( aItemRect );
+ Point aPt = pWindow->OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = pWindow->OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ if( rEvt.GetMode() == HELPMODE_BALLOON )
+ Help::ShowBalloon( pWindow, aItemRect.Center(), aItemRect, aHelpText);
+ else
+ Help::ShowQuickHelp( pWindow, aItemRect, aHelpText );
+ }
+#endif
+ return sal_True;
+}
+
+//------------------------------------------------------------------
+SdrObject* FmFormPage::RemoveObject(ULONG nObjNum)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPage::RemoveObject" );
+ SdrObject* pObj = SdrPage::RemoveObject(nObjNum);
+#ifndef SVX_LIGHT
+ if (pObj && GetModel())
+ ((FmFormModel*)GetModel())->GetUndoEnv().Removed(pObj);
+#endif
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmpgeimp.cxx b/svx/source/form/fmpgeimp.cxx
new file mode 100644
index 000000000000..0fef03f19257
--- /dev/null
+++ b/svx/source/form/fmpgeimp.cxx
@@ -0,0 +1,742 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "svxerr.hxx"
+#include "fmpgeimp.hxx"
+#include "fmundo.hxx"
+#include "svx/fmtools.hxx"
+#include "fmprop.hrc"
+#include "fmservs.hxx"
+#include "fmobj.hxx"
+#include "formcontrolfactory.hxx"
+#include "svditer.hxx"
+#include "fmresids.hrc"
+#include "svx/dbtoolsclient.hxx"
+#include "treevisitor.hxx"
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/container/EnumerableMap.hpp>
+#include <com/sun/star/drawing/XControlShape.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 <tools/shl.hxx>
+#include <vcl/stdtext.hxx>
+#include <svx/dialmgr.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/types.hxx>
+#include <unotools/streamwrap.hxx>
+#include <rtl/logfile.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+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 ::com::sun::star::container::XMap;
+using ::com::sun::star::container::EnumerableMap;
+using ::com::sun::star::drawing::XControlShape;
+using namespace ::svxform;
+
+DBG_NAME(FmFormPageImpl)
+//------------------------------------------------------------------------------
+FmFormPageImpl::FmFormPageImpl( FmFormPage& _rPage )
+ :m_rPage( _rPage )
+ ,m_bFirstActivation( sal_True )
+ ,m_bAttemptedFormCreation( false )
+ ,m_bInFind( false )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::FmFormPageImpl" );
+ DBG_CTOR(FmFormPageImpl,NULL);
+}
+
+//------------------------------------------------------------------------------
+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& _rPage, const FmFormPageImpl& rImpl )
+ :m_rPage( _rPage )
+ ,m_bFirstActivation( sal_True )
+ ,m_bAttemptedFormCreation( false )
+{
+ DBG_CTOR(FmFormPageImpl,NULL);
+
+ // 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 );
+
+ // create a mapping between the original control models and their clones
+ MapControlModels aModelAssignment;
+
+ typedef TreeVisitor< FormComponentPair, FormHierarchyComparator, FormComponentAssignment > FormComponentVisitor;
+ FormComponentVisitor aVisitor = FormComponentVisitor( FormHierarchyComparator() );
+
+ FormComponentAssignment aAssignmentProcessor( aModelAssignment );
+ aVisitor.process( FormComponentPair( xCloneable, m_xForms ), aAssignmentProcessor );
+
+ // assign the cloned models to their SdrObjects
+ SdrObjListIter aForeignIter( rImpl.m_rPage );
+ SdrObjListIter aOwnIter( m_rPage );
+
+ 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() );
+
+ bool bForeignIsForm = pForeignObj && ( pForeignObj->GetObjInventor() == FmFormInventor );
+ bool bOwnIsForm = pOwnObj && ( pOwnObj->GetObjInventor() == FmFormInventor );
+
+ 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& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XMap > FmFormPageImpl::getControlToShapeMap()
+{
+ Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY );
+ if ( xControlShapeMap.is() )
+ return xControlShapeMap;
+
+ xControlShapeMap = impl_createControlShapeMap_nothrow();
+ m_aControlShapeMap = xControlShapeMap;
+ return xControlShapeMap;
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ static void lcl_insertFormObject_throw( const FmFormObj& _object, const Reference< XMap >& _map )
+ {
+ // the control model
+ Reference< XControlModel > xControlModel( _object.GetUnoControlModel(), UNO_QUERY );
+ OSL_ENSURE( xControlModel.is(), "lcl_insertFormObject_throw: suspicious: no control model!" );
+ if ( !xControlModel.is() )
+ return;
+
+ Reference< XControlShape > xControlShape( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY );
+ OSL_ENSURE( xControlShape.is(), "lcl_insertFormObject_throw: suspicious: no control shape!" );
+ if ( !xControlShape.is() )
+ return;
+
+ _map->put( makeAny( xControlModel ), makeAny( xControlShape ) );
+ }
+
+ static void lcl_removeFormObject( const FmFormObj& _object, const Reference< XMap >& _map )
+ {
+ // the control model
+ Reference< XControlModel > xControlModel( _object.GetUnoControlModel(), UNO_QUERY );
+ OSL_ENSURE( xControlModel.is(), "lcl_removeFormObject: suspicious: no control model!" );
+ if ( !xControlModel.is() )
+ return;
+
+ #if OSL_DEBUG_LEVEL > 0
+ Any aOldAssignment =
+ #endif
+ _map->remove( makeAny( xControlModel ) );
+ OSL_ENSURE( aOldAssignment == makeAny( Reference< XControlShape >( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY ) ),
+ "lcl_removeFormObject: map was inconsistent!" );
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XMap > FmFormPageImpl::impl_createControlShapeMap_nothrow()
+{
+ Reference< XMap > xMap;
+
+ try
+ {
+ ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
+ xMap.set( EnumerableMap::create( aContext.getUNOContext(),
+ ::cppu::UnoType< XControlModel >::get(),
+ ::cppu::UnoType< XControlShape >::get()
+ ).get(), UNO_SET_THROW );
+
+ SdrObjListIter aPageIter( m_rPage );
+ while ( aPageIter.IsMore() )
+ {
+ // only FmFormObjs are what we're interested in
+ FmFormObj* pCurrent = FmFormObj::GetFormObject( aPageIter.Next() );
+ if ( !pCurrent )
+ continue;
+
+ lcl_insertFormObject_throw( *pCurrent, xMap );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return xMap;
+}
+
+//------------------------------------------------------------------------------
+const Reference< XNameContainer >& FmFormPageImpl::getForms( bool _bForceCreate )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::getForms" );
+ if ( m_xForms.is() || !_bForceCreate )
+ return m_xForms;
+
+ if ( !m_bAttemptedFormCreation )
+ {
+ m_bAttemptedFormCreation = true;
+
+ const ::rtl::OUString sFormsCollectionServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.Forms") );
+ m_xForms = Reference< XNameContainer > (
+ ::comphelper::getProcessServiceFactory()->createInstance( sFormsCollectionServiceName ),
+ UNO_QUERY
+ );
+ DBG_ASSERT( m_xForms.is(), "FmFormPageImpl::getForms: could not create a forms collection!" );
+
+ if ( m_aFormsCreationHdl.IsSet() )
+ {
+ m_aFormsCreationHdl.Call( this );
+ }
+
+ FmFormModel* pFormsModel = PTR_CAST( FmFormModel, m_rPage.GetModel() );
+
+ // give the newly created collection a place in the universe
+ Reference< XChild > xAsChild( m_xForms, UNO_QUERY );
+ if ( xAsChild.is() )
+ {
+ SfxObjectShell* pObjShell = pFormsModel ? pFormsModel->GetObjectShell() : NULL;
+ if ( pObjShell )
+ xAsChild->setParent( pObjShell->GetModel() );
+ }
+
+ // tell the UNDO environment that we have a new forms collection
+ if ( pFormsModel )
+ pFormsModel->GetUndoEnv().AddForms( m_xForms );
+ }
+ return m_xForms;
+}
+
+//------------------------------------------------------------------------------
+FmFormPageImpl::~FmFormPageImpl()
+{
+ xCurrentForm = NULL;
+
+ ::comphelper::disposeComponent( m_xForms );
+ DBG_DTOR(FmFormPageImpl,NULL);
+}
+
+//------------------------------------------------------------------------------
+bool FmFormPageImpl::validateCurForm()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::validateCurForm" );
+ if ( !xCurrentForm.is() )
+ return false;
+
+ Reference< XChild > xAsChild( xCurrentForm, UNO_QUERY );
+ DBG_ASSERT( xAsChild.is(), "FmFormPageImpl::validateCurForm: a form which is no child??" );
+ if ( !xAsChild.is() || !xAsChild->getParent().is() )
+ xCurrentForm.clear();
+
+ return xCurrentForm.is();
+}
+
+//------------------------------------------------------------------------------
+void FmFormPageImpl::setCurForm(Reference< ::com::sun::star::form::XForm > xForm)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::setCurForm" );
+ xCurrentForm = xForm;
+}
+
+//------------------------------------------------------------------------------
+Reference< XForm > FmFormPageImpl::getDefaultForm()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::getDefaultForm" );
+ Reference< XForm > xForm;
+
+ Reference< XNameContainer > xForms( getForms() );
+
+ // by default, we use our "current form"
+ if ( !validateCurForm() )
+ {
+ // check whether there is a "standard" form
+ if ( xForms->hasElements() )
+ {
+ // suche die Standardform
+ ::rtl::OUString sStandardFormname = String( SVX_RES( RID_STR_STDFORMNAME ) );
+
+ try
+ {
+ if ( xForms->hasByName( sStandardFormname ) )
+ xForm.set( xForms->getByName( sStandardFormname ), UNO_QUERY_THROW );
+ else
+ {
+ Reference< XIndexAccess > xFormsByIndex( xForms, UNO_QUERY_THROW );
+ xForm.set( xFormsByIndex->getByIndex(0), UNO_QUERY_THROW );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ else
+ {
+ xForm = xCurrentForm;
+ }
+
+ // did not find an existing suitable form -> create a new one
+ if ( !xForm.is() )
+ {
+ SdrModel* pModel = m_rPage.GetModel();
+
+ if( pModel->IsUndoEnabled() )
+ {
+ XubString aStr(SVX_RES(RID_STR_FORM));
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+ pModel->BegUndo(aUndoStr);
+ }
+
+ try
+ {
+ xForm.set( ::comphelper::getProcessServiceFactory()->createInstance( FM_SUN_COMPONENT_FORM ), UNO_QUERY );
+
+ // a form should always have the command type table as default
+ Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
+ xFormProps->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny( sal_Int32( CommandType::TABLE ) ) );
+
+ // and the "Standard" name
+ ::rtl::OUString sName = String( SVX_RES( RID_STR_STDFORMNAME ) );
+ xFormProps->setPropertyValue( FM_PROP_NAME, makeAny( sName ) );
+
+ Reference< XIndexContainer > xContainer( xForms, UNO_QUERY );
+ if( pModel->IsUndoEnabled() )
+ {
+ pModel->AddUndo(new FmUndoContainerAction(*(FmFormModel*)pModel,
+ FmUndoContainerAction::Inserted,
+ xContainer,
+ xForm,
+ xContainer->getCount()));
+ }
+ xForms->insertByName( sName, makeAny( xForm ) );
+ xCurrentForm = xForm;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ xForm.clear();
+ }
+
+ if( pModel->IsUndoEnabled() )
+ pModel->EndUndo();
+ }
+
+ return xForm;
+}
+
+//------------------------------------------------------------------------------
+Reference< ::com::sun::star::form::XForm > FmFormPageImpl::findPlaceInFormComponentHierarchy(
+ const Reference< XFormComponent > & rContent, const Reference< XDataSource > & rDatabase,
+ const ::rtl::OUString& rDBTitle, const ::rtl::OUString& rCursorSource, sal_Int32 nCommandType )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::findPlaceInFormComponentHierarchy" );
+ // if the control already is child of a form, don't do anything
+ if (!rContent.is() || rContent->getParent().is())
+ return NULL;
+
+ Reference< XForm > xForm;
+
+ // Wenn Datenbank und CursorSource gesetzt sind, dann wird
+ // die Form anhand dieser Kriterien gesucht, ansonsten nur aktuelle
+ // und die StandardForm
+ if (rDatabase.is() && rCursorSource.getLength())
+ {
+ validateCurForm();
+
+ // erst in der aktuellen form suchen
+ xForm = findFormForDataSource( xCurrentForm, rDatabase, rCursorSource, nCommandType );
+
+ Reference< ::com::sun::star::container::XIndexAccess > xFormsByIndex( getForms(), UNO_QUERY );
+ DBG_ASSERT(xFormsByIndex.is(), "FmFormPageImpl::findPlaceInFormComponentHierarchy : no index access for my forms collection !");
+ sal_Int32 nCount = xFormsByIndex->getCount();
+ for (sal_Int32 i = 0; !xForm.is() && i < nCount; i++)
+ {
+ Reference< ::com::sun::star::form::XForm > xToSearch;
+ xFormsByIndex->getByIndex(i) >>= xToSearch;
+ xForm = findFormForDataSource( xToSearch, rDatabase, rCursorSource, nCommandType );
+ }
+
+ // wenn keine ::com::sun::star::form gefunden, dann eine neue erzeugen
+ if (!xForm.is())
+ {
+ SdrModel* pModel = m_rPage.GetModel();
+
+ const bool bUndo = pModel->IsUndoEnabled();
+
+ if( bUndo )
+ {
+ XubString aStr(SVX_RES(RID_STR_FORM));
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+ pModel->BegUndo(aUndoStr);
+ }
+
+ xForm = Reference< ::com::sun::star::form::XForm >(::comphelper::getProcessServiceFactory()->createInstance(FM_SUN_COMPONENT_FORM), UNO_QUERY);
+ // a form should always have the command type table as default
+ Reference< ::com::sun::star::beans::XPropertySet > xFormProps(xForm, UNO_QUERY);
+ try { xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE))); }
+ catch(Exception&) { }
+
+ if (rDBTitle.getLength())
+ xFormProps->setPropertyValue(FM_PROP_DATASOURCE,makeAny(rDBTitle));
+ else
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xDatabaseProps(rDatabase, UNO_QUERY);
+ Any aDatabaseUrl = xDatabaseProps->getPropertyValue(FM_PROP_URL);
+ xFormProps->setPropertyValue(FM_PROP_DATASOURCE, aDatabaseUrl);
+ }
+
+ xFormProps->setPropertyValue(FM_PROP_COMMAND,makeAny(rCursorSource));
+ xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny(nCommandType));
+
+ Reference< ::com::sun::star::container::XNameAccess > xNamedSet( getForms(), UNO_QUERY );
+
+ const bool bTableOrQuery = ( CommandType::TABLE == nCommandType ) || ( CommandType::QUERY == nCommandType );
+ ::rtl::OUString sName = FormControlFactory::getUniqueName( xNamedSet,
+ bTableOrQuery ? rCursorSource : ::rtl::OUString( String( SVX_RES( RID_STR_STDFORMNAME ) ) ) );
+
+ xFormProps->setPropertyValue( FM_PROP_NAME, makeAny( sName ) );
+
+ if( bUndo )
+ {
+ Reference< ::com::sun::star::container::XIndexContainer > xContainer( getForms(), UNO_QUERY );
+ pModel->AddUndo(new FmUndoContainerAction(*(FmFormModel*)pModel,
+ FmUndoContainerAction::Inserted,
+ xContainer,
+ xForm,
+ xContainer->getCount()));
+ }
+
+ getForms()->insertByName( sName, makeAny( xForm ) );
+
+ if( bUndo )
+ pModel->EndUndo();
+ }
+ xCurrentForm = xForm;
+ }
+
+ xForm = getDefaultForm();
+ return xForm;
+}
+
+//------------------------------------------------------------------------------
+Reference< XForm > FmFormPageImpl::findFormForDataSource(
+ const Reference< XForm > & rForm, const Reference< XDataSource > & _rxDatabase,
+ const ::rtl::OUString& _rCursorSource, sal_Int32 nCommandType)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::findFormForDataSource" );
+ Reference< XForm > xResultForm;
+ Reference< XRowSet > xDBForm(rForm, UNO_QUERY);
+ Reference< XPropertySet > xFormProps(rForm, UNO_QUERY);
+ if (!xDBForm.is() || !xFormProps.is())
+ return xResultForm;
+
+ OSL_ENSURE(_rxDatabase.is(), "FmFormPageImpl::findFormForDataSource: invalid data source!");
+ ::rtl::OUString sLookupName; // the name of the data source we're looking for
+ ::rtl::OUString sFormDataSourceName; // the name of the data source the current connection in the form is based on
+ try
+ {
+ Reference< XPropertySet > xDSProps(_rxDatabase, UNO_QUERY);
+ if (xDSProps.is())
+ xDSProps->getPropertyValue(FM_PROP_NAME) >>= sLookupName;
+
+ xFormProps->getPropertyValue(FM_PROP_DATASOURCE) >>= sFormDataSourceName;
+ // if there's no DataSourceName set at the form, check whether we can deduce one from its
+ // ActiveConnection
+ if (0 == sFormDataSourceName.getLength())
+ {
+ Reference< XConnection > xFormConnection;
+ xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ) >>= xFormConnection;
+ if ( !xFormConnection.is() )
+ OStaticDataAccessTools().isEmbeddedInDatabase( xFormProps, xFormConnection );
+ if (xFormConnection.is())
+ {
+ Reference< XChild > xConnAsChild(xFormConnection, UNO_QUERY);
+ if (xConnAsChild.is())
+ {
+ Reference< XDataSource > xFormDS(xConnAsChild->getParent(), UNO_QUERY);
+ if (xFormDS.is())
+ {
+ xDSProps = xDSProps.query(xFormDS);
+ if (xDSProps.is())
+ xDSProps->getPropertyValue(FM_PROP_NAME) >>= sFormDataSourceName;
+ }
+ }
+ }
+ }
+ }
+ catch(const Exception& e)
+ {
+ (void)e;
+ OSL_ENSURE(sal_False, "FmFormPageImpl::findFormForDataSource: caught an exception!");
+ }
+
+ if (sLookupName == sFormDataSourceName)
+ {
+ // jetzt noch ueberpruefen ob CursorSource und Type uebereinstimmen
+ ::rtl::OUString aCursorSource = ::comphelper::getString(xFormProps->getPropertyValue(FM_PROP_COMMAND));
+ sal_Int32 nType = ::comphelper::getINT32(xFormProps->getPropertyValue(FM_PROP_COMMANDTYPE));
+ if (!aCursorSource.getLength() || ((nType == nCommandType) && (aCursorSource == _rCursorSource))) // found the form
+ {
+ xResultForm = rForm;
+ // Ist noch keine Datenquelle gesetzt, wird dieses hier nachgeholt
+ if (!aCursorSource.getLength())
+ {
+ xFormProps->setPropertyValue(FM_PROP_COMMAND, makeAny(_rCursorSource));
+ xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny((sal_Int32)nCommandType));
+ }
+ }
+ }
+
+ // as long as xResultForm is NULL, search the child forms of rForm
+ Reference< XIndexAccess > xComponents(rForm, UNO_QUERY);
+ sal_Int32 nCount = xComponents->getCount();
+ for (sal_Int32 i = 0; !xResultForm.is() && i < nCount; ++i)
+ {
+ Reference< ::com::sun::star::form::XForm > xSearchForm;
+ xComponents->getByIndex(i) >>= xSearchForm;
+ // continue searching in the sub form
+ if (xSearchForm.is())
+ xResultForm = findFormForDataSource( xSearchForm, _rxDatabase, _rCursorSource, nCommandType );
+ }
+ return xResultForm;
+}
+
+//------------------------------------------------------------------------------
+::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())
+ {
+ sName = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_NAME ) );
+ Reference< ::com::sun::star::container::XNameAccess > xNameAcc(xControls, UNO_QUERY);
+
+ if (!sName.getLength() || xNameAcc->hasByName(sName))
+ {
+ // setzen eines default Namens ueber die ClassId
+ sal_Int16 nClassId( FormComponentType::CONTROL );
+ xSet->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId;
+
+ ::rtl::OUString sDefaultName = FormControlFactory::getDefaultUniqueName_ByComponentType(
+ Reference< XNameAccess >( xControls, UNO_QUERY ), xSet );
+
+ // bei Radiobuttons, die einen Namen haben, diesen nicht ueberschreiben!
+ if (!sName.getLength() || nClassId != ::com::sun::star::form::FormComponentType::RADIOBUTTON)
+ {
+ xSet->setPropertyValue(FM_PROP_NAME, makeAny(sDefaultName));
+ }
+
+ sName = sDefaultName;
+ }
+ }
+ return sName;
+}
+
+//------------------------------------------------------------------
+void FmFormPageImpl::formObjectInserted( const FmFormObj& _object )
+{
+ Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY );
+ if ( !xControlShapeMap.is() )
+ // our map does not exist -> not interested in this event
+ return;
+
+ try
+ {
+ lcl_insertFormObject_throw( _object, xControlShapeMap );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+void FmFormPageImpl::formObjectRemoved( const FmFormObj& _object )
+{
+ Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY );
+ if ( !xControlShapeMap.is() )
+ // our map does not exist -> not interested in this event
+ return;
+
+ try
+ {
+ lcl_removeFormObject( _object, xControlShapeMap );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmscriptingenv.cxx b/svx/source/form/fmscriptingenv.cxx
new file mode 100644
index 000000000000..d18019790523
--- /dev/null
+++ b/svx/source/form/fmscriptingenv.cxx
@@ -0,0 +1,579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmscriptingenv.hxx"
+#include <svx/fmmodel.hxx>
+
+/** === begin UNO includes === **/
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/script/XScriptListener.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+/** === end UNO includes === **/
+#include <tools/diagnose_ex.h>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/implementationreference.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <sfx2/objsh.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::script::XEventAttacherManager;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::script::XScriptListener;
+ using ::com::sun::star::script::ScriptEvent;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::reflection::InvocationTargetException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::container::XHierarchicalNameAccess;
+ using ::com::sun::star::reflection::XInterfaceMethodTypeDescription;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::awt::XControl;
+ using ::com::sun::star::beans::XPropertySet;
+ /** === end UNO using === **/
+
+ class FormScriptingEnvironment;
+
+ //====================================================================
+ //= FormScriptListener
+ //====================================================================
+ typedef ::cppu::WeakImplHelper1 < XScriptListener
+ > FormScriptListener_Base;
+
+ /** implements the XScriptListener interface, is used by FormScriptingEnvironment
+ */
+ class FormScriptListener :public FormScriptListener_Base
+ {
+ private:
+ ::osl::Mutex m_aMutex;
+ ::rtl::Reference< FormScriptingEnvironment > m_pScriptExecutor;
+
+ public:
+ FormScriptListener( const ::rtl::Reference< FormScriptingEnvironment >& _pScriptExecutor );
+
+ // XScriptListener
+ virtual void SAL_CALL firing( const ScriptEvent& aEvent ) throw (RuntimeException);
+ virtual Any SAL_CALL approveFiring( const ScriptEvent& aEvent ) throw (InvocationTargetException, RuntimeException);
+ // XEventListener
+ virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
+
+ // lifetime control
+ void SAL_CALL dispose();
+
+ protected:
+ ~FormScriptListener();
+
+ private:
+ /** determines whether calling a given method at a given listener interface can be done asynchronously
+
+ @param _rListenerType
+ the name of the UNO type whose method is to be checked
+ @param _rMethodName
+ the name of the method at the interface determined by _rListenerType
+
+ @return
+ <TRUE/> if and only if the method is declared <code>oneway</code>, i.e. can be called asynchronously
+ */
+ bool impl_allowAsynchronousCall_nothrow( const ::rtl::OUString& _rListenerType, const ::rtl::OUString& _rMethodName ) const;
+
+ /** determines whether the instance is already disposed
+ */
+ bool impl_isDisposed_nothrow() const { return !m_pScriptExecutor.is(); }
+
+ /** fires the given script event in a thread-safe manner
+
+ This methods calls our script executor's doFireScriptEvent, with previously releasing the given mutex guard,
+ but ensuring that our script executor is not deleted between this release and the actual call.
+
+ @param _rGuard
+ a clearable guard to our mutex. Must be the only active guard to our mutex.
+ @param _rEvent
+ the event to fire
+ @param _pSyncronousResult
+ a place to take a possible result of the script call.
+
+ @precond
+ m_pScriptExecutor is not <NULL/>.
+ */
+ void impl_doFireScriptEvent_nothrow( ::osl::ClearableMutexGuard& _rGuard, const ScriptEvent& _rEvent, Any* _pSyncronousResult );
+
+ private:
+ DECL_LINK( OnAsyncScriptEvent, ScriptEvent* );
+ };
+
+ //====================================================================
+ //= FormScriptingEnvironment
+ //====================================================================
+ class FormScriptingEnvironment : public IFormScriptingEnvironment
+ {
+ private:
+ typedef ::comphelper::ImplementationReference< FormScriptListener, XScriptListener > ListenerImplementation;
+
+ private:
+ ::osl::Mutex m_aMutex;
+ oslInterlockedCount m_refCount;
+ ListenerImplementation m_pScriptListener;
+ FmFormModel& m_rFormModel;
+ bool m_bDisposed;
+
+ public:
+ FormScriptingEnvironment( FmFormModel& _rModel );
+ virtual ~FormScriptingEnvironment();
+
+ // callback for FormScriptListener
+ void doFireScriptEvent( const ScriptEvent& _rEvent, Any* _pSyncronousResult );
+
+ // IFormScriptingEnvironment
+ virtual void registerEventAttacherManager( const Reference< XEventAttacherManager >& _rxManager );
+ virtual void revokeEventAttacherManager( const Reference< XEventAttacherManager >& _rxManager );
+ virtual void dispose();
+
+ // IReference
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+ private:
+ void impl_registerOrRevoke_throw( const Reference< XEventAttacherManager >& _rxManager, bool _bRegister );
+
+ private:
+ FormScriptingEnvironment(); // never implemented
+ FormScriptingEnvironment( const FormScriptingEnvironment& ); // never implemented
+ FormScriptingEnvironment& operator=( const FormScriptingEnvironment& ); // never implemented
+ };
+
+ //====================================================================
+ //= FormScriptListener
+ //====================================================================
+ //--------------------------------------------------------------------
+ FormScriptListener::FormScriptListener( const ::rtl::Reference< FormScriptingEnvironment >& _pScriptExecutor )
+ :m_pScriptExecutor( _pScriptExecutor )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ FormScriptListener::~FormScriptListener()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool FormScriptListener::impl_allowAsynchronousCall_nothrow( const ::rtl::OUString& _rListenerType, const ::rtl::OUString& _rMethodName ) const
+ {
+ bool bAllowAsynchronousCall = false;
+ try
+ {
+ ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
+ Reference< XHierarchicalNameAccess > xTypeDescriptions( aContext.getSingleton( "com.sun.star.reflection.theTypeDescriptionManager" ), UNO_QUERY_THROW );
+
+ ::rtl::OUString sMethodDescription( _rListenerType );
+ sMethodDescription += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "::" ));
+ sMethodDescription += _rMethodName;
+
+ Reference< XInterfaceMethodTypeDescription > xMethod( xTypeDescriptions->getByHierarchicalName( sMethodDescription ), UNO_QUERY_THROW );
+ bAllowAsynchronousCall = xMethod->isOneway();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return bAllowAsynchronousCall;
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptListener::impl_doFireScriptEvent_nothrow( ::osl::ClearableMutexGuard& _rGuard, const ScriptEvent& _rEvent, Any* _pSyncronousResult )
+ {
+ OSL_PRECOND( m_pScriptExecutor.is(), "FormScriptListener::impl_doFireScriptEvent_nothrow: this will crash!" );
+
+ ::rtl::Reference< FormScriptingEnvironment > pExecutor( m_pScriptExecutor );
+ _rGuard.clear();
+ pExecutor->doFireScriptEvent( _rEvent, _pSyncronousResult );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormScriptListener::firing( const ScriptEvent& _rEvent ) throw (RuntimeException)
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ static const ::rtl::OUString vbaInterOp( RTL_CONSTASCII_USTRINGPARAM("VBAInterop") );
+ if ( _rEvent.ScriptType.equals(vbaInterOp) )
+ return; // not handled here
+
+ if ( impl_isDisposed_nothrow() )
+ return;
+
+ if ( !impl_allowAsynchronousCall_nothrow( _rEvent.ListenerType.getTypeName(), _rEvent.MethodName ) )
+ {
+ impl_doFireScriptEvent_nothrow( aGuard, _rEvent, NULL );
+ return;
+ }
+
+ acquire();
+ Application::PostUserEvent( LINK( this, FormScriptListener, OnAsyncScriptEvent ), new ScriptEvent( _rEvent ) );
+ }
+
+ //--------------------------------------------------------------------
+ Any SAL_CALL FormScriptListener::approveFiring( const ScriptEvent& _rEvent ) throw (InvocationTargetException, RuntimeException)
+ {
+ Any aResult;
+
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ if ( !impl_isDisposed_nothrow() )
+ impl_doFireScriptEvent_nothrow( aGuard, _rEvent, &aResult );
+
+ return aResult;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormScriptListener::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
+ {
+ // not interested in
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormScriptListener::dispose()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_pScriptExecutor = NULL;
+ }
+
+ //--------------------------------------------------------------------
+ IMPL_LINK( FormScriptListener, OnAsyncScriptEvent, ScriptEvent*, _pEvent )
+ {
+ OSL_PRECOND( _pEvent != NULL, "FormScriptListener::OnAsyncScriptEvent: invalid event!" );
+ if ( !_pEvent )
+ return 1L;
+
+ {
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ if ( !impl_isDisposed_nothrow() )
+ impl_doFireScriptEvent_nothrow( aGuard, *_pEvent, NULL );
+ }
+
+ delete _pEvent;
+ // we acquired ourself immediately before posting the event
+ release();
+ return 0L;
+ }
+
+ //====================================================================
+ //= FormScriptingEnvironment
+ //====================================================================
+ //--------------------------------------------------------------------
+ FormScriptingEnvironment::FormScriptingEnvironment( FmFormModel& _rModel )
+ :m_refCount( 0 )
+ ,m_pScriptListener( NULL )
+ ,m_rFormModel( _rModel )
+ ,m_bDisposed( false )
+ {
+ m_pScriptListener = ListenerImplementation( new FormScriptListener( this ) );
+ // note that this is a cyclic reference between the FormScriptListener and the FormScriptingEnvironment
+ // This cycle is broken up when our instance is disposed.
+ }
+
+ //--------------------------------------------------------------------
+ FormScriptingEnvironment::~FormScriptingEnvironment()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptingEnvironment::impl_registerOrRevoke_throw( const Reference< XEventAttacherManager >& _rxManager, bool _bRegister )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !_rxManager.is() )
+ throw IllegalArgumentException();
+ if ( m_bDisposed )
+ throw DisposedException();
+
+ try
+ {
+ if ( _bRegister )
+ _rxManager->addScriptListener( m_pScriptListener.getRef() );
+ else
+ _rxManager->removeScriptListener( m_pScriptListener.getRef() );
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptingEnvironment::registerEventAttacherManager( const Reference< XEventAttacherManager >& _rxManager )
+ {
+ impl_registerOrRevoke_throw( _rxManager, true );
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptingEnvironment::revokeEventAttacherManager( const Reference< XEventAttacherManager >& _rxManager )
+ {
+ impl_registerOrRevoke_throw( _rxManager, false );
+ }
+
+ //--------------------------------------------------------------------
+ oslInterlockedCount SAL_CALL FormScriptingEnvironment::acquire()
+ {
+ return osl_incrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ oslInterlockedCount SAL_CALL FormScriptingEnvironment::release()
+ {
+ if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
+ {
+ delete this;
+ return 0;
+ }
+ return m_refCount;
+ }
+
+ //--------------------------------------------------------------------
+ IFormScriptingEnvironment::~IFormScriptingEnvironment()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ //................................................................
+ //. NewStyleUNOScript
+ //................................................................
+ class SAL_NO_VTABLE IScript
+ {
+ public:
+ virtual void invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult ) = 0;
+
+ virtual ~IScript() { }
+ };
+ typedef ::boost::shared_ptr< IScript > PScript;
+
+ //................................................................
+ //. NewStyleUNOScript
+ //................................................................
+ class NewStyleUNOScript : public IScript
+ {
+ SfxObjectShell& m_rObjectShell;
+ const ::rtl::OUString m_sScriptCode;
+
+ public:
+ NewStyleUNOScript( SfxObjectShell& _rObjectShell, const ::rtl::OUString& _rScriptCode )
+ :m_rObjectShell( _rObjectShell )
+ ,m_sScriptCode( _rScriptCode )
+ {
+ }
+
+ // IScript
+ virtual void invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult );
+ };
+
+ //................................................................
+ void NewStyleUNOScript::invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult )
+ {
+ Sequence< sal_Int16 > aOutArgsIndex;
+ Sequence< Any > aOutArgs;
+ EventObject aEvent;
+ Any aCaller;
+ if ( ( _rArguments.getLength() > 0 ) && ( _rArguments[ 0 ] >>= aEvent ) )
+ {
+ try
+ {
+ Reference< XControl > xControl( aEvent.Source, UNO_QUERY_THROW );
+ Reference< XPropertySet > xProps( xControl->getModel(), UNO_QUERY_THROW );
+ aCaller = xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) );
+ }
+ catch( Exception& ) {}
+ }
+ m_rObjectShell.CallXScript( m_sScriptCode, _rArguments, _rSynchronousResult, aOutArgsIndex, aOutArgs, true, aCaller.hasValue() ? &aCaller : 0 );
+ }
+
+ //................................................................
+ //. QualifiedBasicScript
+ //................................................................
+ class QualifiedBasicScript : public IScript
+ {
+ SfxObjectShell& m_rObjectShell;
+ const ::rtl::OUString m_sMacroLocation;
+ const ::rtl::OUString m_sScriptCode;
+
+ public:
+ QualifiedBasicScript( SfxObjectShell& _rObjectShell, const ::rtl::OUString& _rLocation, const ::rtl::OUString& _rScriptCode )
+ :m_rObjectShell( _rObjectShell )
+ ,m_sMacroLocation( _rLocation )
+ ,m_sScriptCode( _rScriptCode )
+ {
+ }
+
+ // IScript
+ virtual void invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult );
+ };
+
+ //................................................................
+ void QualifiedBasicScript::invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult )
+ {
+ m_rObjectShell.CallStarBasicScript( m_sScriptCode, m_sMacroLocation,
+ &_rArguments, &_rSynchronousResult );
+ }
+
+ //................................................................
+ //. UnqualifiedBasicScript
+ //................................................................
+ class UnqualifiedBasicScript : public IScript
+ {
+ SfxObjectShell& m_rObjectShell;
+ const ::rtl::OUString m_sScriptCode;
+
+ public:
+ UnqualifiedBasicScript( SfxObjectShell& _rObjectShell, const ::rtl::OUString& _rScriptCode )
+ :m_rObjectShell( _rObjectShell )
+ ,m_sScriptCode( _rScriptCode )
+ {
+ }
+
+ // IScript
+ virtual void invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult );
+ };
+
+ //................................................................
+ void UnqualifiedBasicScript::invoke( const Sequence< Any >& _rArguments, Any& _rSynchronousResult )
+ {
+ m_rObjectShell.CallScript( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) ), m_sScriptCode,
+ &_rArguments, &_rSynchronousResult );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptingEnvironment::doFireScriptEvent( const ScriptEvent& _rEvent, Any* _pSyncronousResult )
+ {
+ SolarMutexClearableGuard aSolarGuard;
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ if ( m_bDisposed )
+ return;
+
+ SfxObjectShellRef xObjectShell = m_rFormModel.GetObjectShell();
+ if( !xObjectShell.Is() )
+ return;
+
+ // the script to execute
+ PScript pScript;
+
+ if ( !_rEvent.ScriptType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StarBasic" ) ) )
+ {
+ pScript.reset( new NewStyleUNOScript( *xObjectShell, _rEvent.ScriptCode ) );
+ }
+ else
+ {
+ ::rtl::OUString sScriptCode = _rEvent.ScriptCode;
+ ::rtl::OUString sMacroLocation;
+
+ // is there a location in the script name ("application" or "document")?
+ sal_Int32 nPrefixLen = sScriptCode.indexOf( ':' );
+ DBG_ASSERT( 0 <= nPrefixLen, "FormScriptingEnvironment::doFireScriptEvent: Basic script name in old format encountered!" );
+
+ if ( 0 <= nPrefixLen )
+ {
+ // and it has such a prefix
+ sMacroLocation = sScriptCode.copy( 0, nPrefixLen );
+ DBG_ASSERT( 0 == sMacroLocation.compareToAscii( "document" )
+ || 0 == sMacroLocation.compareToAscii( "application" ),
+ "FormScriptingEnvironment::doFireScriptEvent: invalid (unknown) prefix!" );
+
+ // strip the prefix: the SfxObjectShell::CallScript knows nothing about such prefixes
+ sScriptCode = sScriptCode.copy( nPrefixLen + 1 );
+ }
+
+ if ( sMacroLocation.getLength() )
+ { // we have a StarBasic macro with fully-qualified macro location
+ pScript.reset( new QualifiedBasicScript( *xObjectShell, sMacroLocation, sScriptCode ) );
+ }
+ else
+ { // we have a StarBasic macro without qualified location - let the object shell gues ....
+ pScript.reset( new UnqualifiedBasicScript( *xObjectShell, sScriptCode ) );
+ }
+ }
+
+ OSL_ENSURE( pScript.get(), "FormScriptingEnvironment::doFireScriptEvent: no script to execute!" );
+ if ( !pScript.get() )
+ // this is an internal error in the above code
+ throw RuntimeException();
+
+ aGuard.clear();
+ aSolarGuard.clear();
+
+ Any aIgnoreResult;
+ pScript->invoke( _rEvent.Arguments, _pSyncronousResult ? *_pSyncronousResult : aIgnoreResult );
+ pScript.reset();
+
+ {
+ // object shells are not thread safe, so guard the destruction
+ SolarMutexGuard aSolarGuarsReset;
+ xObjectShell = NULL;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void FormScriptingEnvironment::dispose()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_bDisposed = true;
+ m_pScriptListener->dispose();
+ }
+
+ //--------------------------------------------------------------------
+ PFormScriptingEnvironment createDefaultFormScriptingEnvironment( FmFormModel& _rModel )
+ {
+ return new FormScriptingEnvironment( _rModel );
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmservs.cxx b/svx/source/form/fmservs.cxx
new file mode 100644
index 000000000000..45ceb61db6c1
--- /dev/null
+++ b/svx/source/form/fmservs.cxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <com/sun/star/container/XSet.hpp>
+#include <cppuhelper/factory.hxx>
+#include <comphelper/processfactory.hxx>
+#include "fmservs.hxx"
+
+// ------------------------------------------------------------------------
+#define DECL_SERVICE(ImplName) \
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ImplName##_NewInstance_Impl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &) throw( ::com::sun::star::uno::Exception );
+
+#define REGISTER_SERVICE(ImplName, ServiceName) \
+ sString = (ServiceName); \
+ xSingleFactory = ::cppu::createSingleFactory(xServiceFactory, \
+ ::rtl::OUString(), ImplName##_NewInstance_Impl, \
+ ::com::sun::star::uno::Sequence< ::rtl::OUString>(&sString, 1)); \
+ if (xSingleFactory.is()) \
+ xSet->insert(::com::sun::star::uno::makeAny(xSingleFactory));
+
+
+ DECL_SERVICE( FmXGridControl )
+ DECL_SERVICE( FormController )
+ DECL_SERVICE( LegacyFormController )
+
+
+// ------------------------------------------------------------------------
+namespace svxform
+{
+
+#define DECL_SELFAWARE_SERVICE( ClassName ) \
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ClassName##_Create( \
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ); \
+ ::rtl::OUString SAL_CALL ClassName##_GetImplementationName(); \
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL ClassName##_GetSupportedServiceNames(); \
+
+
+#define REGISTER_SELFAWARE_SERVICE( ClassName ) \
+ xSingleFactory = ::cppu::createSingleFactory( xServiceFactory, \
+ ClassName##_GetImplementationName(), \
+ ClassName##_Create, \
+ ClassName##_GetSupportedServiceNames() \
+ ); \
+ if ( xSingleFactory.is() ) \
+ xSet->insert( ::com::sun::star::uno::makeAny( xSingleFactory ) );
+
+
+ // ------------------------------------------------------------------------
+ DECL_SELFAWARE_SERVICE( OAddConditionDialog )
+
+ // ------------------------------------------------------------------------
+ void ImplSmartRegisterUnoServices()
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory(::comphelper::getProcessServiceFactory(), ::com::sun::star::uno::UNO_QUERY);
+ ::com::sun::star::uno::Reference< ::com::sun::star::container::XSet > xSet(xServiceFactory, ::com::sun::star::uno::UNO_QUERY);
+ if (!xSet.is())
+ return;
+
+ ::com::sun::star::uno::Sequence< ::rtl::OUString> aServices;
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XSingleServiceFactory > xSingleFactory;
+
+ ::rtl::OUString sString;
+
+ // ------------------------------------------------------------------------
+ // FormController
+ REGISTER_SERVICE( FormController, FM_FORM_CONTROLLER );
+ REGISTER_SERVICE( LegacyFormController, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.FormController" ) ) );
+
+ // ------------------------------------------------------------------------
+ // FormController
+ REGISTER_SELFAWARE_SERVICE( OAddConditionDialog );
+
+ // ------------------------------------------------------------------------
+ // DBGridControl
+ REGISTER_SERVICE(FmXGridControl, FM_CONTROL_GRID); // compatibility
+ REGISTER_SERVICE(FmXGridControl, FM_CONTROL_GRIDCONTROL);
+ REGISTER_SERVICE(FmXGridControl, FM_SUN_CONTROL_GRIDCONTROL);
+ };
+
+} // namespace svxform
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmshell.cxx b/svx/source/form/fmshell.cxx
new file mode 100644
index 000000000000..827a2f3bcfcf
--- /dev/null
+++ b/svx/source/form/fmshell.cxx
@@ -0,0 +1,1513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmvwimp.hxx"
+#include <svx/fmshell.hxx>
+#include "svx/fmtools.hxx"
+#include "fmservs.hxx"
+#include "fmprop.hrc"
+#include "fmpgeimp.hxx"
+#include "fmitems.hxx"
+#include "fmundo.hxx"
+#include <vcl/waitobj.hxx>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/msgbox.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/app.hxx>
+#include <svl/intitem.hxx>
+#include <svl/visitem.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objsh.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/fmpage.hxx>
+#include "svditer.hxx"
+#include "fmobj.hxx"
+
+#include <svx/svxids.hrc>
+
+#include "fmresids.hrc"
+#include "fmexch.hxx"
+#include <svx/fmglob.hxx>
+#include <svl/eitem.hxx>
+#include <tools/shl.hxx>
+#include <tools/diagnose_ex.h>
+#include <svx/svdpage.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/dialmgr.hxx>
+#include "fmshimp.hxx"
+#include <svx/svdpagv.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/viewsh.hxx>
+#include <vcl/sound.hxx>
+#include "fmexpl.hxx"
+#include "formcontrolling.hxx"
+#include <svl/numuno.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/processfactory.hxx>
+#include "fmdocumentclassification.hxx"
+#include "formtoolbars.hxx"
+
+#include <svx/svxdlg.hxx>
+#include <svx/dialogs.hrc>
+
+#include "svx/sdrobjectfilter.hxx"
+
+#define HANDLE_SQL_ERRORS( action, successflag, context, message ) \
+ try \
+ { \
+ successflag = sal_False; \
+ action; \
+ successflag = sal_True; \
+ } \
+ catch(::com::sun::star::sdbc::SQLException& e) \
+ { \
+ ::com::sun::star::sdb::SQLContext eExtendedInfo = \
+ GetImpl()->prependContextInfo(e, Reference< XInterface > (), context, ::rtl::OUString()); \
+ displayException(eExtendedInfo); \
+ } \
+ catch(Exception&) \
+ { \
+ DBG_ERROR(message); \
+ } \
+
+
+#define DO_SAFE_WITH_ERROR( action, message ) try { action; } catch(Exception&) { DBG_ERROR(message); }
+
+#define FmFormShell
+#include "svxslots.hxx"
+
+#include <svx/svxids.hrc>
+#include "tbxform.hxx"
+#include <comphelper/property.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+// wird fuer Invalidate verwendet -> mitpflegen
+// aufsteigend sortieren !!!!!!
+sal_uInt16 ControllerSlotMap[] = // slots des Controllers
+{
+ SID_FM_CONFIG,
+ SID_FM_PUSHBUTTON,
+ SID_FM_RADIOBUTTON,
+ SID_FM_CHECKBOX,
+ SID_FM_FIXEDTEXT,
+ SID_FM_GROUPBOX,
+ SID_FM_EDIT,
+ SID_FM_LISTBOX,
+ SID_FM_COMBOBOX,
+ SID_FM_DBGRID,
+ SID_FM_IMAGEBUTTON,
+ SID_FM_FILECONTROL,
+ SID_FM_NAVIGATIONBAR,
+ SID_FM_CTL_PROPERTIES,
+ SID_FM_PROPERTIES,
+ SID_FM_TAB_DIALOG,
+ SID_FM_ADD_FIELD,
+ SID_FM_DESIGN_MODE,
+ SID_FM_SHOW_FMEXPLORER,
+ SID_FM_SHOW_PROPERTIES,
+ SID_FM_FMEXPLORER_CONTROL,
+ SID_FM_DATEFIELD,
+ SID_FM_TIMEFIELD,
+ SID_FM_NUMERICFIELD,
+ SID_FM_CURRENCYFIELD,
+ SID_FM_PATTERNFIELD,
+ SID_FM_OPEN_READONLY,
+ SID_FM_IMAGECONTROL,
+ SID_FM_USE_WIZARDS,
+ SID_FM_FORMATTEDFIELD,
+ SID_FM_FILTER_NAVIGATOR,
+ SID_FM_AUTOCONTROLFOCUS,
+ SID_FM_SCROLLBAR,
+ SID_FM_SPINBUTTON,
+ SID_FM_SHOW_DATANAVIGATOR,
+ SID_FM_DATANAVIGATOR_CONTROL,
+
+ 0
+};
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::form::runtime;
+using namespace ::com::sun::star::frame;
+using namespace ::svxform;
+
+//========================================================================
+// class FmDesignModeChangedHint
+//========================================================================
+TYPEINIT1( FmDesignModeChangedHint, SfxHint );
+
+//------------------------------------------------------------------------
+FmDesignModeChangedHint::FmDesignModeChangedHint( sal_Bool bDesMode )
+ :m_bDesignMode( bDesMode )
+{
+}
+
+//------------------------------------------------------------------------
+FmDesignModeChangedHint::~FmDesignModeChangedHint()
+{
+}
+
+//========================================================================
+const sal_uInt32 FM_UI_FEATURE_SHOW_DATABASEBAR = 0x00000001;
+const sal_uInt32 FM_UI_FEATURE_SHOW_FIELD = 0x00000002;
+const sal_uInt32 FM_UI_FEATURE_SHOW_PROPERTIES = 0x00000004;
+const sal_uInt32 FM_UI_FEATURE_SHOW_EXPLORER = 0x00000008;
+const sal_uInt32 FM_UI_FEATURE_SHOW_FILTERBAR = 0x00000010;
+const sal_uInt32 FM_UI_FEATURE_SHOW_FILTERNAVIGATOR = 0x00000020;
+const sal_uInt32 FM_UI_FEATURE_SHOW_TEXT_CONTROL_BAR = 0x00000040;
+const sal_uInt32 FM_UI_FEATURE_TB_CONTROLS = 0x00000080;
+const sal_uInt32 FM_UI_FEATURE_TB_MORECONTROLS = 0x00000100;
+const sal_uInt32 FM_UI_FEATURE_TB_FORMDESIGN = 0x00000200;
+const sal_uInt32 FM_UI_FEATURE_SHOW_DATANAVIGATOR = 0x00000400;
+
+SFX_IMPL_INTERFACE(FmFormShell, SfxShell, SVX_RES(RID_STR_FORMSHELL))
+{
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_NAVIGATION|SFX_VISIBILITY_STANDARD|SFX_VISIBILITY_READONLYDOC,
+ SVX_RES(RID_SVXTBX_FORM_NAVIGATION),
+ FM_UI_FEATURE_SHOW_DATABASEBAR );
+
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_NAVIGATION|SFX_VISIBILITY_STANDARD|SFX_VISIBILITY_READONLYDOC,
+ SVX_RES(RID_SVXTBX_FORM_FILTER),
+ FM_UI_FEATURE_SHOW_FILTERBAR );
+
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD | SFX_VISIBILITY_READONLYDOC,
+ SVX_RES( RID_SVXTBX_TEXT_CONTROL_ATTRIBUTES ),
+ FM_UI_FEATURE_SHOW_TEXT_CONTROL_BAR );
+
+ SFX_FEATURED_CHILDWINDOW_REGISTRATION(SID_FM_ADD_FIELD, FM_UI_FEATURE_SHOW_FIELD);
+ SFX_FEATURED_CHILDWINDOW_REGISTRATION(SID_FM_SHOW_PROPERTIES, FM_UI_FEATURE_SHOW_PROPERTIES);
+ SFX_FEATURED_CHILDWINDOW_REGISTRATION(SID_FM_SHOW_FMEXPLORER, FM_UI_FEATURE_SHOW_EXPLORER);
+ SFX_FEATURED_CHILDWINDOW_REGISTRATION(SID_FM_FILTER_NAVIGATOR, FM_UI_FEATURE_SHOW_FILTERNAVIGATOR);
+ SFX_FEATURED_CHILDWINDOW_REGISTRATION(SID_FM_SHOW_DATANAVIGATOR, FM_UI_FEATURE_SHOW_DATANAVIGATOR);
+
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD,
+ SVX_RES( RID_SVXTBX_CONTROLS ),
+ FM_UI_FEATURE_TB_CONTROLS );
+
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD,
+ SVX_RES( RID_SVXTBX_MORECONTROLS ),
+ FM_UI_FEATURE_TB_MORECONTROLS );
+
+ SFX_FEATURED_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD,
+ SVX_RES( RID_SVXTBX_FORMDESIGN ),
+ FM_UI_FEATURE_TB_FORMDESIGN );
+}
+
+//========================================================================
+TYPEINIT1(FmFormShell,SfxShell)
+
+//------------------------------------------------------------------------
+FmFormShell::FmFormShell( SfxViewShell* _pParent, FmFormView* pView )
+ :SfxShell(_pParent)
+ ,m_pImpl(new FmXFormShell(*this, _pParent->GetViewFrame()))
+ ,m_pFormView( pView )
+ ,m_pFormModel( NULL )
+ ,m_pParentShell(_pParent)
+ ,m_nLastSlot( 0 )
+ ,m_bDesignMode( sal_True )
+ ,m_bHasForms(sal_False)
+{
+ m_pImpl->acquire();
+ SetPool( &SFX_APP()->GetPool() );
+ SetName( String::CreateFromAscii( "Form" ) );
+
+ SetView(m_pFormView);
+}
+
+//------------------------------------------------------------------------
+FmFormShell::~FmFormShell()
+{
+ if ( m_pFormView )
+ SetView( NULL );
+
+ m_pImpl->dispose();
+ m_pImpl->release();
+ m_pImpl = NULL;
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::NotifyMarkListChanged(FmFormView* pWhichView)
+{
+ FmNavViewMarksChanged aChangeNotification(pWhichView);
+ Broadcast(aChangeNotification);
+}
+
+//------------------------------------------------------------------------
+sal_uInt16 FmFormShell::PrepareClose(sal_Bool bUI, sal_Bool bForBrowsing)
+{
+ if ( GetImpl()->didPrepareClose() )
+ // we already did a PrepareClose for the current modifications of the current form
+ // 2002-11-12 #104702# - fs@openoffice.org
+ return sal_True;
+
+ sal_Bool bResult = sal_True;
+ // Save the data records, not in DesignMode and FilterMode
+ if (!m_bDesignMode && !GetImpl()->isInFilterMode() &&
+ m_pFormView && m_pFormView->GetActualOutDev() &&
+ m_pFormView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
+ {
+ SdrPageView* pCurPageView = m_pFormView->GetSdrPageView();
+
+ // sal_uInt16 nPos = pCurPageView ? pCurPageView->GetWinList().Find((OutputDevice*)m_pFormView->GetActualOutDev()) : SDRPAGEVIEWWIN_NOTFOUND;
+ SdrPageWindow* pWindow = pCurPageView ? pCurPageView->FindPageWindow(*((OutputDevice*)m_pFormView->GetActualOutDev())) : 0L;
+
+ if(pWindow)
+ {
+ // Zunaechst werden die aktuellen Inhalte der Controls gespeichert
+ // Wenn alles glatt gelaufen ist, werden die modifizierten Datensaetze gespeichert
+ if ( GetImpl()->getActiveController().is() )
+ {
+ const ::svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures();
+ if ( rController->commitCurrentControl() )
+ {
+ sal_Bool bModified = rController->isModifiedRow();
+
+ if ( bModified && bUI )
+ {
+ QueryBox aQry(NULL, SVX_RES(RID_QRY_SAVEMODIFIED));
+ if (bForBrowsing)
+ aQry.AddButton(SVX_RES(RID_STR_NEW_TASK), RET_NEWTASK,
+ BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON);
+
+ switch (aQry.Execute())
+ {
+ case RET_NO:
+ bModified = sal_False;
+ GetImpl()->didPrepareClose( sal_True );
+ break;
+
+ case RET_CANCEL:
+ return sal_False;
+
+ case RET_NEWTASK:
+ return RET_NEWTASK;
+ }
+
+ if ( bModified )
+ bResult = rController->commitCurrentRecord( );
+ }
+ }
+ }
+ }
+ }
+ return bResult;
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::impl_setDesignMode(sal_Bool bDesign)
+{
+ if (m_pFormView)
+ {
+ if (!bDesign)
+ m_nLastSlot = SID_FM_DESIGN_MODE;
+
+ GetImpl()->SetDesignMode(bDesign);
+ // mein m_bDesignMode wird auch von der Impl gesetzt ...
+ }
+ else
+ {
+ m_bHasForms = sal_False;
+ m_bDesignMode = bDesign;
+ UIFeatureChanged();
+ }
+
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate(ControllerSlotMap);
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFormShell::HasUIFeature( sal_uInt32 nFeature )
+{
+ sal_Bool bResult = sal_False;
+ if ((nFeature & FM_UI_FEATURE_SHOW_DATABASEBAR) == FM_UI_FEATURE_SHOW_DATABASEBAR)
+ {
+ // nur wenn auch formulare verfuegbar
+ bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar() && !GetImpl()->isInFilterMode();
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_FILTERBAR) == FM_UI_FEATURE_SHOW_FILTERBAR)
+ {
+ // nur wenn auch formulare verfuegbar
+ bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar() && GetImpl()->isInFilterMode();
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_FILTERNAVIGATOR) == FM_UI_FEATURE_SHOW_FILTERNAVIGATOR)
+ {
+ bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar() && GetImpl()->isInFilterMode();
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_FIELD) == FM_UI_FEATURE_SHOW_FIELD)
+ {
+ bResult = m_bDesignMode && m_pFormView && m_bHasForms;
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_PROPERTIES) == FM_UI_FEATURE_SHOW_PROPERTIES)
+ {
+ bResult = m_bDesignMode && m_pFormView && m_bHasForms;
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_EXPLORER) == FM_UI_FEATURE_SHOW_EXPLORER)
+ {
+ bResult = m_bDesignMode; // OJ #101593# && m_pFormView && m_bHasForms;
+ }
+ else if ( ( nFeature & FM_UI_FEATURE_SHOW_TEXT_CONTROL_BAR ) == FM_UI_FEATURE_SHOW_TEXT_CONTROL_BAR )
+ {
+ bResult = !GetImpl()->IsReadonlyDoc() && m_pImpl->IsActiveControl( true );
+ }
+ else if ((nFeature & FM_UI_FEATURE_SHOW_DATANAVIGATOR) == FM_UI_FEATURE_SHOW_DATANAVIGATOR)
+ {
+ bResult = GetImpl()->isEnhancedForm();
+ }
+ else if ( ( ( nFeature & FM_UI_FEATURE_TB_CONTROLS ) == FM_UI_FEATURE_TB_CONTROLS )
+ || ( ( nFeature & FM_UI_FEATURE_TB_MORECONTROLS ) == FM_UI_FEATURE_TB_MORECONTROLS )
+ || ( ( nFeature & FM_UI_FEATURE_TB_FORMDESIGN ) == FM_UI_FEATURE_TB_FORMDESIGN )
+ )
+ {
+ bResult = sal_True;
+ }
+
+ return bResult;
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::Execute(SfxRequest &rReq)
+{
+ sal_uInt16 nSlot = rReq.GetSlot();
+
+ //////////////////////////////////////////////////////////////////////
+ // MasterSlot setzen
+ switch( nSlot )
+ {
+ case SID_FM_PUSHBUTTON:
+ case SID_FM_RADIOBUTTON:
+ case SID_FM_CHECKBOX:
+ case SID_FM_FIXEDTEXT:
+ case SID_FM_GROUPBOX:
+ case SID_FM_LISTBOX:
+ case SID_FM_COMBOBOX:
+ case SID_FM_NAVIGATIONBAR:
+ case SID_FM_EDIT:
+ case SID_FM_DBGRID:
+ case SID_FM_IMAGEBUTTON:
+ case SID_FM_IMAGECONTROL:
+ case SID_FM_FILECONTROL:
+ case SID_FM_DATEFIELD:
+ case SID_FM_TIMEFIELD:
+ case SID_FM_NUMERICFIELD:
+ case SID_FM_CURRENCYFIELD:
+ case SID_FM_PATTERNFIELD:
+ case SID_FM_FORMATTEDFIELD:
+ case SID_FM_SCROLLBAR:
+ case SID_FM_SPINBUTTON:
+ m_nLastSlot = nSlot;
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_FM_CONFIG );
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Identifier und Inventor des Uno-Controls setzen
+ sal_uInt16 nIdentifier = 0;
+ switch( nSlot )
+ {
+ case SID_FM_CHECKBOX:
+ nIdentifier = OBJ_FM_CHECKBOX;
+ break;
+ case SID_FM_PUSHBUTTON:
+ nIdentifier = OBJ_FM_BUTTON;
+ break;
+ case SID_FM_FIXEDTEXT:
+ nIdentifier = OBJ_FM_FIXEDTEXT;
+ break;
+ case SID_FM_LISTBOX:
+ nIdentifier = OBJ_FM_LISTBOX;
+ break;
+ case SID_FM_EDIT:
+ nIdentifier = OBJ_FM_EDIT;
+ break;
+ case SID_FM_RADIOBUTTON:
+ nIdentifier = OBJ_FM_RADIOBUTTON;
+ break;
+ case SID_FM_GROUPBOX:
+ nIdentifier = OBJ_FM_GROUPBOX;
+ break;
+ case SID_FM_COMBOBOX:
+ nIdentifier = OBJ_FM_COMBOBOX;
+ break;
+ case SID_FM_NAVIGATIONBAR:
+ nIdentifier = OBJ_FM_NAVIGATIONBAR;
+ break;
+ case SID_FM_DBGRID:
+ nIdentifier = OBJ_FM_GRID;
+ break;
+ case SID_FM_IMAGEBUTTON:
+ nIdentifier = OBJ_FM_IMAGEBUTTON;
+ break;
+ case SID_FM_IMAGECONTROL:
+ nIdentifier = OBJ_FM_IMAGECONTROL;
+ break;
+ case SID_FM_FILECONTROL:
+ nIdentifier = OBJ_FM_FILECONTROL;
+ break;
+ case SID_FM_DATEFIELD:
+ nIdentifier = OBJ_FM_DATEFIELD;
+ break;
+ case SID_FM_TIMEFIELD:
+ nIdentifier = OBJ_FM_TIMEFIELD;
+ break;
+ case SID_FM_NUMERICFIELD:
+ nIdentifier = OBJ_FM_NUMERICFIELD;
+ break;
+ case SID_FM_CURRENCYFIELD:
+ nIdentifier = OBJ_FM_CURRENCYFIELD;
+ break;
+ case SID_FM_PATTERNFIELD:
+ nIdentifier = OBJ_FM_PATTERNFIELD;
+ break;
+ case SID_FM_FORMATTEDFIELD:
+ nIdentifier = OBJ_FM_FORMATTEDFIELD;
+ break;
+ case SID_FM_SCROLLBAR:
+ nIdentifier = OBJ_FM_SCROLLBAR;
+ break;
+ case SID_FM_SPINBUTTON:
+ nIdentifier = OBJ_FM_SPINBUTTON;
+ break;
+ }
+
+ switch ( nSlot )
+ {
+ case SID_FM_CHECKBOX:
+ case SID_FM_PUSHBUTTON:
+ case SID_FM_FIXEDTEXT:
+ case SID_FM_LISTBOX:
+ case SID_FM_EDIT:
+ case SID_FM_RADIOBUTTON:
+ case SID_FM_COMBOBOX:
+ case SID_FM_NAVIGATIONBAR:
+ case SID_FM_GROUPBOX:
+ case SID_FM_DBGRID:
+ case SID_FM_IMAGEBUTTON:
+ case SID_FM_IMAGECONTROL:
+ case SID_FM_FILECONTROL:
+ case SID_FM_DATEFIELD:
+ case SID_FM_TIMEFIELD:
+ case SID_FM_NUMERICFIELD:
+ case SID_FM_CURRENCYFIELD:
+ case SID_FM_PATTERNFIELD:
+ case SID_FM_FORMATTEDFIELD:
+ case SID_FM_SCROLLBAR:
+ case SID_FM_SPINBUTTON:
+ {
+ SFX_REQUEST_ARG( rReq, pGrabFocusItem, SfxBoolItem, SID_FM_TOGGLECONTROLFOCUS, sal_False );
+ if ( pGrabFocusItem && pGrabFocusItem->GetValue() )
+ { // see below
+ SfxViewShell* pShell = GetViewShell();
+ Window* pShellWnd = pShell ? pShell->GetWindow() : NULL;
+ if ( pShellWnd )
+ pShellWnd->GrabFocus();
+ break;
+ }
+
+ SfxUInt16Item aIdentifierItem( SID_FM_CONTROL_IDENTIFIER, nIdentifier );
+ SfxUInt32Item aInventorItem( SID_FM_CONTROL_INVENTOR, FmFormInventor );
+ const SfxPoolItem* pArgs[] =
+ {
+ &aIdentifierItem, &aInventorItem, NULL
+ };
+ const SfxPoolItem* pInternalArgs[] =
+ {
+ NULL
+ };
+
+ GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_CREATE_CONTROL, SFX_CALLMODE_ASYNCHRON,
+ pArgs, rReq.GetModifier(), pInternalArgs );
+
+ if ( rReq.GetModifier() & KEY_MOD1 )
+ {
+ // #99013# if selected with control key, return focus to current view
+ // do this asynchron, so that the creation can be finished first
+ // reusing the SID_FM_TOGGLECONTROLFOCUS is somewhat hacky ... which it wouldn't if it would have another
+ // name, so I do not really have a big problem with this ....
+ SfxBoolItem aGrabFocusIndicatorItem( SID_FM_TOGGLECONTROLFOCUS, sal_True );
+ GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( nSlot, SFX_CALLMODE_ASYNCHRON,
+ &aGrabFocusIndicatorItem, NULL );
+ }
+
+ rReq.Done();
+ } break;
+ }
+
+ // Individuelle Aktionen
+ switch( nSlot )
+ {
+ case SID_FM_MORE_CONTROLS:
+ case SID_FM_FORM_DESIGN_TOOLS:
+ {
+ FormToolboxes aToolboxAccess( GetImpl()->getHostFrame() );
+ aToolboxAccess.toggleToolbox( nSlot );
+ rReq.Done();
+ }
+ break;
+
+ case SID_FM_TOGGLECONTROLFOCUS:
+ {
+ FmFormView* pFormView = GetFormView();
+ if ( !pFormView )
+ break;
+
+ // if we execute this ourself, then either the application does not implement an own handling for this,
+ // of we're on the top of the dispatcher stack, which means a control has the focus.
+ // In the latter case, we put the focus to the document window, otherwise, we focus the first control
+ const bool bHasControlFocus = GetImpl()->HasControlFocus();
+ if ( bHasControlFocus )
+ {
+ const OutputDevice* pDevice = GetCurrentViewDevice();
+ Window* pWindow = dynamic_cast< Window* >( const_cast< OutputDevice* >( pDevice ) );
+ if ( pWindow )
+ pWindow->GrabFocus();
+ }
+ else
+ {
+ pFormView->GrabFirstControlFocus( );
+ }
+ }
+ break;
+
+ case SID_FM_VIEW_AS_GRID:
+ GetImpl()->CreateExternalView();
+ break;
+ case SID_FM_CONVERTTO_EDIT :
+ case SID_FM_CONVERTTO_BUTTON :
+ case SID_FM_CONVERTTO_FIXEDTEXT :
+ case SID_FM_CONVERTTO_LISTBOX :
+ case SID_FM_CONVERTTO_CHECKBOX :
+ case SID_FM_CONVERTTO_RADIOBUTTON :
+ case SID_FM_CONVERTTO_GROUPBOX :
+ case SID_FM_CONVERTTO_COMBOBOX :
+ case SID_FM_CONVERTTO_IMAGEBUTTON :
+ case SID_FM_CONVERTTO_FILECONTROL :
+ case SID_FM_CONVERTTO_DATE :
+ case SID_FM_CONVERTTO_TIME :
+ case SID_FM_CONVERTTO_NUMERIC :
+ case SID_FM_CONVERTTO_CURRENCY :
+ case SID_FM_CONVERTTO_PATTERN :
+ case SID_FM_CONVERTTO_IMAGECONTROL :
+ case SID_FM_CONVERTTO_FORMATTED :
+ case SID_FM_CONVERTTO_SCROLLBAR :
+ case SID_FM_CONVERTTO_SPINBUTTON :
+ case SID_FM_CONVERTTO_NAVIGATIONBAR :
+ GetImpl()->executeControlConversionSlot( nSlot );
+ // nach dem Konvertieren die Selektion neu bestimmern, da sich ja das selektierte Objekt
+ // geaendert hat
+ GetImpl()->SetSelection(GetFormView()->GetMarkedObjectList());
+ break;
+ case SID_FM_LEAVE_CREATE:
+ m_nLastSlot = 0;
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_FM_CONFIG );
+ rReq.Done();
+ break;
+ case SID_FM_SHOW_PROPERTY_BROWSER:
+ {
+ SFX_REQUEST_ARG( rReq, pShowItem, SfxBoolItem, SID_FM_SHOW_PROPERTIES, sal_False );
+ sal_Bool bShow = sal_True;
+ if ( pShowItem )
+ bShow = pShowItem->GetValue();
+ GetImpl()->ShowSelectionProperties( bShow );
+
+ rReq.Done();
+ } break;
+
+ case SID_FM_PROPERTIES:
+ {
+ // PropertyBrowser anzeigen
+ SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nSlot, sal_False);
+ sal_Bool bShow = pShowItem ? pShowItem->GetValue() : sal_True;
+
+ InterfaceBag aOnlyTheForm;
+ aOnlyTheForm.insert( Reference< XInterface >( GetImpl()->getCurrentForm(), UNO_QUERY ) );
+ GetImpl()->setCurrentSelection( aOnlyTheForm );
+
+ GetImpl()->ShowSelectionProperties( bShow );
+
+ rReq.Done();
+ } break;
+
+ case SID_FM_CTL_PROPERTIES:
+ {
+ SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nSlot, sal_False);
+ sal_Bool bShow = pShowItem ? pShowItem->GetValue() : sal_True;
+
+ OSL_ENSURE( GetImpl()->onlyControlsAreMarked(), "FmFormShell::Execute: ControlProperties should be disabled!" );
+ if ( bShow )
+ GetImpl()->selectLastMarkedControls();
+ GetImpl()->ShowSelectionProperties( bShow );
+
+ rReq.Done();
+ } break;
+ case SID_FM_SHOW_PROPERTIES:
+ case SID_FM_ADD_FIELD:
+ case SID_FM_FILTER_NAVIGATOR:
+ case SID_FM_SHOW_DATANAVIGATOR :
+ {
+ GetViewShell()->GetViewFrame()->ChildWindowExecute( rReq );
+ rReq.Done();
+ } break;
+ case SID_FM_SHOW_FMEXPLORER:
+ {
+ if (!m_pFormView) // setzen der ::com::sun::star::sdbcx::View Forcieren
+ GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_CREATE_SW_DRAWVIEW);
+
+ GetViewShell()->GetViewFrame()->ChildWindowExecute(rReq);
+ rReq.Done();
+ }
+ break;
+
+ case SID_FM_TAB_DIALOG:
+ {
+ GetImpl()->ExecuteTabOrderDialog( Reference< XTabControllerModel >( GetImpl()->getCurrentForm(), UNO_QUERY ) );
+ rReq.Done();
+ }
+ break;
+
+ case SID_FM_DESIGN_MODE:
+ {
+ SFX_REQUEST_ARG(rReq, pDesignItem, SfxBoolItem, nSlot, sal_False);
+ sal_Bool bDesignMode = pDesignItem ? pDesignItem->GetValue() : !m_bDesignMode;
+ SetDesignMode( bDesignMode );
+ if ( m_bDesignMode == bDesignMode )
+ rReq.Done();
+
+ m_nLastSlot = SID_FM_DESIGN_MODE;
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_FM_CONFIG );
+ }
+ break;
+
+ case SID_FM_AUTOCONTROLFOCUS:
+ {
+ FmFormModel* pModel = GetFormModel();
+ DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !");
+ // should have been disabled in GetState if we don't have a FormModel
+ pModel->SetAutoControlFocus( !pModel->GetAutoControlFocus() );
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS);
+ }
+ break;
+ case SID_FM_OPEN_READONLY:
+ {
+ FmFormModel* pModel = GetFormModel();
+ DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !");
+ // should have been disabled in GetState if we don't have a FormModel
+ pModel->SetOpenInDesignMode( !pModel->GetOpenInDesignMode() );
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY);
+ }
+ break;
+ case SID_FM_USE_WIZARDS:
+ {
+ GetImpl()->SetWizardUsing(!GetImpl()->GetWizardUsing());
+ GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_USE_WIZARDS);
+ }
+ break;
+ case SID_FM_SEARCH:
+ {
+ const ::svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures();
+ if ( rController->commitCurrentControl() && rController->commitCurrentRecord() )
+ GetImpl()->ExecuteSearch();
+ rReq.Done();
+ }
+ break;
+
+ case SID_FM_RECORD_FIRST:
+ case SID_FM_RECORD_PREV:
+ case SID_FM_RECORD_NEXT:
+ case SID_FM_RECORD_LAST:
+ case SID_FM_RECORD_NEW:
+ case SID_FM_REFRESH:
+ case SID_FM_REFRESH_FORM_CONTROL:
+ case SID_FM_RECORD_DELETE:
+ case SID_FM_RECORD_UNDO:
+ case SID_FM_RECORD_SAVE:
+ case SID_FM_REMOVE_FILTER_SORT:
+ case SID_FM_SORTDOWN:
+ case SID_FM_SORTUP:
+ case SID_FM_AUTOFILTER:
+ case SID_FM_ORDERCRIT:
+ case SID_FM_FORM_FILTERED:
+ {
+ GetImpl()->ExecuteFormSlot( nSlot );
+ rReq.Done();
+ }
+ break;
+
+ case SID_FM_RECORD_ABSOLUTE:
+ {
+ const ::svx::ControllerFeatures& rController = GetImpl()->getNavControllerFeatures();
+ sal_Int32 nRecord = -1;
+
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ if ( pArgs )
+ {
+ const SfxPoolItem* pItem;
+ if ( ( pArgs->GetItemState( FN_PARAM_1, sal_True, &pItem ) ) == SFX_ITEM_SET )
+ {
+ const SfxInt32Item* pTypedItem = PTR_CAST( SfxInt32Item, pItem );
+ if ( pTypedItem )
+ nRecord = Max( pTypedItem->GetValue(), sal_Int32(0) );
+ }
+ }
+ else
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ DBG_ASSERT( pFact, "no dialog factory!" );
+ if ( pFact )
+ {
+ ::std::auto_ptr< AbstractFmInputRecordNoDialog > dlg( pFact->CreateFmInputRecordNoDialog( NULL ) );
+ DBG_ASSERT( dlg.get(), "Dialogdiet fail!" );
+ dlg->SetValue( rController->getCursor()->getRow() );
+ if ( dlg->Execute() == RET_OK )
+ nRecord = dlg->GetValue();
+
+ rReq.AppendItem( SfxInt32Item( FN_PARAM_1, nRecord ) );
+ }
+ }
+
+ if ( nRecord != -1 )
+ rController->execute( nSlot, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Position" )), makeAny( (sal_Int32)nRecord ) );
+
+ rReq.Done();
+ } break;
+ case SID_FM_FILTER_EXECUTE:
+ case SID_FM_FILTER_EXIT:
+ {
+ sal_Bool bCancelled = ( SID_FM_FILTER_EXIT == nSlot );
+ sal_Bool bReopenNavigator = sal_False;
+
+ if ( !bCancelled )
+ {
+ // if the filter navigator is still open, we need to close it, so it can possibly
+ // commit it's most recent changes
+ if ( GetViewShell() && GetViewShell()->GetViewFrame() )
+ if ( GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_FILTER_NAVIGATOR ) )
+ {
+ GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
+ bReopenNavigator = sal_True;
+ }
+
+ Reference< runtime::XFormController > xController( GetImpl()->getActiveController() );
+
+ if ( GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_FILTER_NAVIGATOR )
+ // closing the window was denied, for instance because of a invalid criterion
+
+ || ( xController.is()
+ && !GetImpl()->getActiveControllerFeatures()->commitCurrentControl( )
+ )
+ // committing the controller was denied
+ )
+ {
+ rReq.Done();
+ break;
+ }
+ }
+
+ GetImpl()->stopFiltering( !bCancelled );
+ rReq.Done();
+
+ if ( bReopenNavigator )
+ // we closed the navigator only to implicitly commit it (as we do not have another
+ // direct wire to it), but to the user, it should look it it was always open
+ GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
+ }
+ break;
+
+ case SID_FM_FILTER_START:
+ {
+ GetImpl()->startFiltering();
+ rReq.Done();
+
+ // initially open the filter navigator, the whole form based filter is pretty useless without it
+ SfxBoolItem aIdentifierItem( SID_FM_FILTER_NAVIGATOR, TRUE );
+ GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_FILTER_NAVIGATOR, SFX_CALLMODE_ASYNCHRON,
+ &aIdentifierItem, NULL );
+ } break;
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::GetState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ switch( nWhich )
+ {
+ case SID_FM_MORE_CONTROLS:
+ case SID_FM_FORM_DESIGN_TOOLS:
+ {
+ FormToolboxes aToolboxAccess( GetImpl()->getHostFrame() );
+ rSet.Put( SfxBoolItem( nWhich, aToolboxAccess.isToolboxVisible( nWhich ) ) );
+ }
+ break;
+
+ case SID_FM_FILTER_EXECUTE:
+ case SID_FM_FILTER_EXIT:
+ if (!GetImpl()->isInFilterMode())
+ rSet.DisableItem( nWhich );
+ break;
+
+ case SID_FM_USE_WIZARDS:
+ if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
+ rSet.Put( SfxVisibilityItem( nWhich, sal_False ) );
+ else if (!m_bDesignMode || !GetFormModel())
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, GetImpl()->GetWizardUsing() ) );
+ break;
+ case SID_FM_AUTOCONTROLFOCUS:
+ if (!m_bDesignMode || !GetFormModel())
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetAutoControlFocus() ) );
+ break;
+ case SID_FM_OPEN_READONLY:
+ if (!m_bDesignMode || !GetFormModel())
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetOpenInDesignMode() ) );
+ break;
+
+ case SID_FM_NAVIGATIONBAR:
+ case SID_FM_DBGRID:
+ if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
+ {
+ rSet.Put( SfxVisibilityItem( nWhich, sal_False ) );
+ break;
+ }
+ // NO break!
+
+ case SID_FM_SCROLLBAR:
+ case SID_FM_IMAGECONTROL:
+ case SID_FM_FILECONTROL:
+ case SID_FM_CURRENCYFIELD:
+ case SID_FM_PATTERNFIELD:
+ case SID_FM_IMAGEBUTTON:
+ case SID_FM_RADIOBUTTON:
+ case SID_FM_COMBOBOX:
+ case SID_FM_GROUPBOX:
+ case SID_FM_CHECKBOX:
+ case SID_FM_PUSHBUTTON:
+ case SID_FM_FIXEDTEXT:
+ case SID_FM_LISTBOX:
+ case SID_FM_EDIT:
+ case SID_FM_DATEFIELD:
+ case SID_FM_TIMEFIELD:
+ case SID_FM_NUMERICFIELD:
+ case SID_FM_FORMATTEDFIELD:
+ case SID_FM_SPINBUTTON:
+ if (!m_bDesignMode)
+ rSet.DisableItem( nWhich );
+ else
+ {
+ sal_Bool bLayerLocked = sal_False;
+ if (m_pFormView)
+ {
+ // Ist der ::com::sun::star::drawing::Layer gelocked, so m???ssen die Slots disabled werden. #36897
+ SdrPageView* pPV = m_pFormView->GetSdrPageView();
+ if (pPV != NULL)
+ bLayerLocked = pPV->IsLayerLocked(m_pFormView->GetActiveLayer());
+ }
+ if (bLayerLocked)
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, (nWhich==m_nLastSlot)) );
+ }
+ break;
+ case SID_FM_FILTER_NAVIGATOR_CONTROL:
+ {
+ if (GetImpl()->isInFilterMode())
+ rSet.Put(SfxObjectItem(nWhich, this));
+ else
+ rSet.Put(SfxObjectItem(nWhich));
+ } break;
+ case SID_FM_FIELDS_CONTROL:
+ case SID_FM_PROPERTY_CONTROL:
+ {
+ if (!m_bDesignMode || !m_pFormView || !m_bHasForms)
+ rSet.Put(SfxObjectItem(nWhich));
+ else
+ rSet.Put(SfxObjectItem(nWhich, this));
+
+ } break;
+ case SID_FM_FMEXPLORER_CONTROL:
+ case SID_FM_DATANAVIGATOR_CONTROL :
+ {
+ if (!m_bDesignMode || !m_pFormView)
+ rSet.Put(SfxObjectItem(nWhich));
+ else
+ rSet.Put(SfxObjectItem(nWhich, this));
+
+ } break;
+ case SID_FM_ADD_FIELD:
+ case SID_FM_SHOW_FMEXPLORER:
+ case SID_FM_SHOW_PROPERTIES:
+ case SID_FM_FILTER_NAVIGATOR:
+ case SID_FM_SHOW_DATANAVIGATOR:
+ {
+ if ( GetViewShell()->GetViewFrame()->KnowsChildWindow(nWhich) )
+ rSet.Put( SfxBoolItem( nWhich, GetViewShell()->GetViewFrame()->HasChildWindow(nWhich)) );
+ else
+ rSet.DisableItem(nWhich);
+ } break;
+
+ case SID_FM_SHOW_PROPERTY_BROWSER:
+ {
+ rSet.Put(SfxBoolItem(GetImpl()->IsPropBrwOpen()));
+ }
+ break;
+
+ case SID_FM_CTL_PROPERTIES:
+ {
+ // der Impl eventuell die Moeglichjkeit geben, ihre an der aktuellen MarkList ausgerichteten Objekte
+ // auf den neuesten Stand zu bringen
+ if (GetImpl()->IsSelectionUpdatePending())
+ GetImpl()->ForceUpdateSelection(sal_False);
+
+ if ( !m_pFormView || !m_bDesignMode || !GetImpl()->onlyControlsAreMarked() )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ sal_Bool bChecked = GetImpl()->IsPropBrwOpen() && !GetImpl()->isSolelySelected( GetImpl()->getCurrentForm() );
+ // if the property browser is open, and only controls are marked, and the current selection
+ // does not consist of only the current form, then the current selection is the (composition of)
+ // the currently marked controls
+ rSet.Put( SfxBoolItem( nWhich, bChecked ) );
+ }
+ } break;
+
+ case SID_FM_PROPERTIES:
+ {
+ // der Impl eventuell die Moeglichjkeit geben, ihre an der aktuellen MarkList ausgerichteten Objekte
+ // auf den neuesten Stand zu bringen
+ if (GetImpl()->IsSelectionUpdatePending())
+ GetImpl()->ForceUpdateSelection(sal_False);
+
+ if ( !m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm().is() )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ sal_Bool bChecked = GetImpl()->IsPropBrwOpen() && GetImpl()->isSolelySelected( GetImpl()->getCurrentForm() );
+ rSet.Put(SfxBoolItem(nWhich, bChecked));
+ }
+ } break;
+ case SID_FM_TAB_DIALOG:
+ // der Impl eventuell die Moeglichjkeit geben, ihre an der aktuellen MarkList ausgerichteten Objekte
+ // auf den neuesten Stand zu bringen
+ if (GetImpl()->IsSelectionUpdatePending())
+ GetImpl()->ForceUpdateSelection(sal_False);
+
+ if (!m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm().is() )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_FM_CONFIG:
+ rSet.Put(SfxUInt16Item(nWhich, m_nLastSlot));
+ break;
+ case SID_FM_DESIGN_MODE:
+ if (!m_pFormView || GetImpl()->IsReadonlyDoc() )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem(nWhich, m_bDesignMode) );
+ break;
+ case SID_FM_SEARCH:
+ case SID_FM_RECORD_FIRST:
+ case SID_FM_RECORD_NEXT:
+ case SID_FM_RECORD_PREV:
+ case SID_FM_RECORD_LAST:
+ case SID_FM_RECORD_NEW:
+ case SID_FM_RECORD_DELETE:
+ case SID_FM_RECORD_ABSOLUTE:
+ case SID_FM_RECORD_TOTAL:
+ case SID_FM_RECORD_SAVE:
+ case SID_FM_RECORD_UNDO:
+ case SID_FM_FORM_FILTERED:
+ case SID_FM_REMOVE_FILTER_SORT:
+ case SID_FM_SORTUP:
+ case SID_FM_SORTDOWN:
+ case SID_FM_ORDERCRIT:
+ case SID_FM_FILTER_START:
+ case SID_FM_AUTOFILTER:
+ case SID_FM_REFRESH:
+ case SID_FM_REFRESH_FORM_CONTROL:
+ case SID_FM_VIEW_AS_GRID:
+ GetFormState(rSet,nWhich);
+ break;
+
+ case SID_FM_CHANGECONTROLTYPE:
+ {
+ if ( !m_pFormView || !m_bDesignMode )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ if ( !GetImpl()->canConvertCurrentSelectionToControl( OBJ_FM_FIXEDTEXT ) )
+ // if it cannot be converted to a fixed text, it is no single control
+ rSet.DisableItem( nWhich );
+ }
+ } break;
+
+ case SID_FM_CONVERTTO_FILECONTROL :
+ case SID_FM_CONVERTTO_CURRENCY :
+ case SID_FM_CONVERTTO_PATTERN :
+ case SID_FM_CONVERTTO_IMAGECONTROL :
+ case SID_FM_CONVERTTO_SCROLLBAR :
+ case SID_FM_CONVERTTO_NAVIGATIONBAR :
+ case SID_FM_CONVERTTO_IMAGEBUTTON :
+ case SID_FM_CONVERTTO_EDIT :
+ case SID_FM_CONVERTTO_BUTTON :
+ case SID_FM_CONVERTTO_FIXEDTEXT :
+ case SID_FM_CONVERTTO_LISTBOX :
+ case SID_FM_CONVERTTO_CHECKBOX :
+ case SID_FM_CONVERTTO_RADIOBUTTON :
+ case SID_FM_CONVERTTO_GROUPBOX :
+ case SID_FM_CONVERTTO_COMBOBOX :
+ case SID_FM_CONVERTTO_DATE :
+ case SID_FM_CONVERTTO_TIME :
+ case SID_FM_CONVERTTO_NUMERIC :
+ case SID_FM_CONVERTTO_FORMATTED :
+ case SID_FM_CONVERTTO_SPINBUTTON :
+ {
+ if ( !m_pFormView || !m_bDesignMode || !GetImpl()->canConvertCurrentSelectionToControl( nWhich ) )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ rSet.Put( SfxBoolItem( nWhich, sal_False ) );
+ // just to have a defined state (available and not checked)
+ }
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::GetFormState(SfxItemSet &rSet, sal_uInt16 nWhich)
+{
+ if ( !GetImpl()->getNavController().is()
+ || !isRowSetAlive(GetImpl()->getNavController()->getModel())
+ || !m_pFormView
+ || m_bDesignMode
+ || !GetImpl()->getActiveForm().is()
+ || GetImpl()->isInFilterMode()
+ )
+ rSet.DisableItem(nWhich);
+ else
+ {
+ sal_Bool bEnable = sal_False;
+ try
+ {
+ switch (nWhich)
+ {
+ case SID_FM_VIEW_AS_GRID:
+ if (GetImpl()->getHostFrame().is() && GetImpl()->getNavController().is())
+ {
+ bEnable = sal_True;
+ sal_Bool bDisplayingCurrent =
+ GetImpl()->getInternalForm(
+ Reference< XForm >( GetImpl()->getNavController()->getModel(), UNO_QUERY )
+ ) == GetImpl()->getExternallyDisplayedForm();
+ rSet.Put(SfxBoolItem(nWhich, bDisplayingCurrent));
+ }
+ break;
+
+ case SID_FM_SEARCH:
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xNavSet(GetImpl()->getActiveForm(), UNO_QUERY);
+ sal_Int32 nCount = ::comphelper::getINT32(xNavSet->getPropertyValue(FM_PROP_ROWCOUNT));
+ bEnable = nCount != 0;
+ } break;
+ case SID_FM_RECORD_ABSOLUTE:
+ case SID_FM_RECORD_TOTAL:
+ {
+ FeatureState aState;
+ GetImpl()->getNavControllerFeatures()->getState( nWhich, aState );
+ if ( SID_FM_RECORD_ABSOLUTE == nWhich )
+ {
+ sal_Int32 nPosition = 0;
+ aState.State >>= nPosition;
+ rSet.Put( SfxInt32Item( nWhich, nPosition ) );
+ }
+ else if ( SID_FM_RECORD_TOTAL == nWhich )
+ {
+ ::rtl::OUString sTotalCount;
+ aState.State >>= sTotalCount;
+ rSet.Put( SfxStringItem( nWhich, sTotalCount ) );
+ }
+ bEnable = aState.Enabled;
+ }
+ break;
+
+ // first, prev, next, last, and absolute affect the nav controller, not the
+ // active controller
+ case SID_FM_RECORD_FIRST:
+ case SID_FM_RECORD_PREV:
+ case SID_FM_RECORD_NEXT:
+ case SID_FM_RECORD_LAST:
+ case SID_FM_RECORD_NEW:
+ case SID_FM_RECORD_SAVE:
+ case SID_FM_RECORD_UNDO:
+ case SID_FM_RECORD_DELETE:
+ case SID_FM_REFRESH:
+ case SID_FM_REFRESH_FORM_CONTROL:
+ case SID_FM_REMOVE_FILTER_SORT:
+ case SID_FM_SORTUP:
+ case SID_FM_SORTDOWN:
+ case SID_FM_AUTOFILTER:
+ case SID_FM_ORDERCRIT:
+ bEnable = GetImpl()->IsFormSlotEnabled( nWhich );
+ break;
+
+ case SID_FM_FORM_FILTERED:
+ {
+ FeatureState aState;
+ bEnable = GetImpl()->IsFormSlotEnabled( nWhich, &aState );
+
+ rSet.Put( SfxBoolItem( nWhich, ::comphelper::getBOOL( aState.State ) ) );
+ }
+ break;
+
+ case SID_FM_FILTER_START:
+ bEnable = GetImpl()->getActiveControllerFeatures()->canDoFormFilter();
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "FmFormShell::GetFormState: caught an exception while determining the state!" );
+ }
+ if (!bEnable)
+ rSet.DisableItem(nWhich);
+ }
+}
+
+//------------------------------------------------------------------------
+FmFormPage* FmFormShell::GetCurPage() const
+{
+ FmFormPage* pP = NULL;
+ if (m_pFormView && m_pFormView->GetSdrPageView())
+ pP = PTR_CAST(FmFormPage,m_pFormView->GetSdrPageView()->GetPage());
+ return pP;
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::SetView( FmFormView* _pView )
+{
+ if ( m_pFormView )
+ {
+ if ( IsActive() )
+ GetImpl()->viewDeactivated( *m_pFormView );
+
+ m_pFormView->SetFormShell( NULL, FmFormView::FormShellAccess() );
+ m_pFormView = NULL;
+ m_pFormModel = NULL;
+ }
+
+ if ( !_pView )
+ return;
+
+ m_pFormView = _pView;
+ m_pFormView->SetFormShell( this, FmFormView::FormShellAccess() );
+ m_pFormModel = (FmFormModel*)m_pFormView->GetModel();
+
+ impl_setDesignMode( m_pFormView->IsDesignMode() );
+
+ // We activate our view if we are activated ourself, but sometimes the Activate precedes the SetView.
+ // But here we know both the view and our activation state so we at least are able to pass the latter
+ // to the former.
+ // FS - 30.06.99 - 67308
+ if ( IsActive() )
+ GetImpl()->viewActivated( *m_pFormView );
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::DetermineForms(sal_Bool bInvalidate)
+{
+ // Existieren Formulare auf der aktuellen Page
+ sal_Bool bForms = GetImpl()->hasForms();
+ if (bForms != m_bHasForms)
+ {
+ m_bHasForms = bForms;
+ if (bInvalidate)
+ UIFeatureChanged();
+ }
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFormShell::GetY2KState(sal_uInt16& nReturn)
+{
+ return GetImpl()->GetY2KState(nReturn);
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::SetY2KState(sal_uInt16 n)
+{
+ GetImpl()->SetY2KState(n);
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::Activate(sal_Bool bMDI)
+{
+ SfxShell::Activate(bMDI);
+
+ if ( m_pFormView )
+ GetImpl()->viewActivated( *m_pFormView, sal_True );
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::Deactivate(sal_Bool bMDI)
+{
+ SfxShell::Deactivate(bMDI);
+
+ if ( m_pFormView )
+ GetImpl()->viewDeactivated( *m_pFormView, sal_False );
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::ExecuteTextAttribute( SfxRequest& _rReq )
+{
+ m_pImpl->ExecuteTextAttribute( _rReq );
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::GetTextAttributeState( SfxItemSet& _rSet )
+{
+ m_pImpl->GetTextAttributeState( _rSet );
+}
+
+//------------------------------------------------------------------------
+bool FmFormShell::IsActiveControl() const
+{
+ return m_pImpl->IsActiveControl();
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::ForgetActiveControl()
+{
+ m_pImpl->ForgetActiveControl();
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::SetControlActivationHandler( const Link& _rHdl )
+{
+ m_pImpl->SetControlActivationHandler( _rHdl );
+}
+
+//------------------------------------------------------------------------
+namespace
+{
+ SdrUnoObj* lcl_findUnoObject( const SdrObjList& _rObjList, const Reference< XControlModel >& _rxModel )
+ {
+ SdrObjListIter aIter( _rObjList );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pObject = aIter.Next();
+ SdrUnoObj* pUnoObject = pObject ? PTR_CAST( SdrUnoObj, pObject ) : NULL;
+ if ( !pUnoObject )
+ continue;
+
+ Reference< XControlModel > xControlModel = pUnoObject->GetUnoControlModel();
+ if ( !xControlModel.is() )
+ continue;
+
+ if ( _rxModel == xControlModel )
+ return pUnoObject;
+ }
+ return NULL;
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::ToggleControlFocus( const SdrUnoObj& i_rUnoObject, const SdrView& i_rView, OutputDevice& i_rDevice ) const
+{
+ try
+ {
+ // check if the focus currently is in a control
+ // Well, okay, do it the other way 'round: Check whether the current control of the active controller
+ // actually has the focus. This should be equivalent.
+ const bool bHasControlFocus = GetImpl()->HasControlFocus();
+
+ if ( bHasControlFocus )
+ {
+ Window* pWindow( dynamic_cast< Window* >( &i_rDevice ) );
+ OSL_ENSURE( pWindow, "FmFormShell::ToggleControlFocus: I need a Window, really!" );
+ if ( pWindow )
+ pWindow->GrabFocus();
+ }
+ else
+ {
+ Reference< XControl > xControl;
+ GetFormControl( i_rUnoObject.GetUnoControlModel(), i_rView, i_rDevice, xControl );
+ Reference< XWindow > xControlWindow( xControl, UNO_QUERY );
+ if ( xControlWindow.is() )
+ xControlWindow->setFocus();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------
+namespace
+{
+ class FocusableControlsFilter : public ::svx::ISdrObjectFilter
+ {
+ public:
+ FocusableControlsFilter( const SdrView& i_rView, const OutputDevice& i_rDevice )
+ :m_rView( i_rView )
+ ,m_rDevice( i_rDevice )
+ {
+ }
+
+ public:
+ virtual bool includeObject( const SdrObject& i_rObject ) const
+ {
+ const SdrUnoObj* pUnoObj = dynamic_cast< const SdrUnoObj* >( &i_rObject );
+ if ( !pUnoObj )
+ return false;
+
+ Reference< XControl > xControl = pUnoObj->GetUnoControl( m_rView, m_rDevice );
+ return FmXFormView::isFocusable( xControl );
+ }
+
+ private:
+ const SdrView& m_rView;
+ const OutputDevice& m_rDevice;
+ };
+}
+
+//------------------------------------------------------------------------
+::std::auto_ptr< ::svx::ISdrObjectFilter > FmFormShell::CreateFocusableControlFilter( const SdrView& i_rView, const OutputDevice& i_rDevice ) const
+{
+ ::std::auto_ptr< ::svx::ISdrObjectFilter > pFilter;
+
+ if ( !i_rView.IsDesignMode() )
+ pFilter.reset( new FocusableControlsFilter( i_rView, i_rDevice ) );
+
+ return pFilter;
+}
+
+//------------------------------------------------------------------------
+SdrUnoObj* FmFormShell::GetFormControl( const Reference< XControlModel >& _rxModel, const SdrView& _rView, const OutputDevice& _rDevice, Reference< XControl >& _out_rxControl ) const
+{
+ if ( !_rxModel.is() )
+ return NULL;
+
+ // we can only retrieve controls for SdrObjects which belong to page which is actually displayed in the given view
+ SdrPageView* pPageView = _rView.GetSdrPageView();
+ SdrPage* pPage = pPageView ? pPageView->GetPage() : NULL;
+ OSL_ENSURE( pPage, "FmFormShell::GetFormControl: no page displayed in the given view!" );
+ if ( !pPage )
+ return NULL;
+
+ SdrUnoObj* pUnoObject = lcl_findUnoObject( *pPage, _rxModel );
+ if ( pUnoObject )
+ {
+ _out_rxControl = pUnoObject->GetUnoControl( _rView, _rDevice );
+ return pUnoObject;
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ // perhaps we are fed with a control model which lives on a page other than the one displayed
+ // in the given view. This is worth being reported as error, in non-product builds.
+ FmFormModel* pModel = GetFormModel();
+ if ( pModel )
+ {
+ sal_uInt16 pageCount = pModel->GetPageCount();
+ for ( sal_uInt16 page = 0; page < pageCount; ++page )
+ {
+ pPage = pModel->GetPage( page );
+ OSL_ENSURE( pPage, "FmFormShell::GetFormControl: NULL page encountered!" );
+ if ( !pPage )
+ continue;
+
+ pUnoObject = lcl_findUnoObject( *pPage, _rxModel );
+ OSL_ENSURE( !pUnoObject, "FmFormShell::GetFormControl: the given control model belongs to a wrong page (displayed elsewhere)!" );
+ }
+ }
+#endif
+
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+Reference< runtime::XFormController > FmFormShell::GetFormController( const Reference< XForm >& _rxForm, const SdrView& _rView, const OutputDevice& _rDevice ) const
+{
+ const FmFormView* pFormView = dynamic_cast< const FmFormView* >( &_rView );
+ if ( !pFormView )
+ return NULL;
+
+ return pFormView->GetFormController( _rxForm, _rDevice );
+}
+
+//------------------------------------------------------------------------
+void FmFormShell::SetDesignMode( sal_Bool _bDesignMode )
+{
+ if ( _bDesignMode == m_bDesignMode )
+ return;
+
+ FmFormModel* pModel = GetFormModel();
+ if (pModel)
+ // fuer die Zeit des Uebergangs das Undo-Environment ausschalten, das sichert, dass man dort auch nicht-transiente
+ // Properties mal eben aendern kann (sollte allerdings mit Vorsicht genossen und beim Rueckschalten des Modes
+ // auch immer wieder rueckgaegig gemacht werden. Ein Beispiel ist das Setzen der maximalen Text-Laenge durch das
+ // OEditModel an seinem Control.)
+ pModel->GetUndoEnv().Lock();
+
+ // dann die eigentliche Umschaltung
+ if ( m_bDesignMode || PrepareClose( sal_True ) )
+ impl_setDesignMode(!m_bDesignMode );
+
+ // und mein Undo-Environment wieder an
+ if ( pModel )
+ pModel->GetUndoEnv().UnLock();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmshimp.cxx b/svx/source/form/fmshimp.cxx
new file mode 100644
index 000000000000..cf39a32ca903
--- /dev/null
+++ b/svx/source/form/fmshimp.cxx
@@ -0,0 +1,4340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+#include "fmitems.hxx"
+#include "fmobj.hxx"
+#include "fmpgeimp.hxx"
+#include "svx/fmtools.hxx"
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "fmshimp.hxx"
+#include "fmtextcontrolshell.hxx"
+#include "fmundo.hxx"
+#include "fmurl.hxx"
+#include "fmvwimp.hxx"
+#include "formtoolbars.hxx"
+#include "gridcols.hxx"
+#include "svditer.hxx"
+#include "svx/dialmgr.hxx"
+#include "svx/dialogs.hrc"
+#include "svx/fmglob.hxx"
+#include "svx/fmmodel.hxx"
+#include "svx/fmpage.hxx"
+#include "svx/fmshell.hxx"
+#include "svx/obj3d.hxx"
+#include "svx/sdrpagewindow.hxx"
+#include "svx/svdpagv.hxx"
+#include "svx/svxdlg.hxx"
+#include "svx/svxids.hrc"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/XCheckBox.hpp>
+#include <com/sun/star/awt/XListBox.hpp>
+#include <com/sun/star/awt/XTextComponent.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/form/ListSourceType.hpp>
+#include <com/sun/star/form/XBoundComponent.hpp>
+#include <com/sun/star/form/XBoundControl.hpp>
+#include <com/sun/star/form/XGrid.hpp>
+#include <com/sun/star/form/XGridPeer.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/form/binding/XBindableValue.hpp>
+#include <com/sun/star/form/binding/XListEntrySink.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <com/sun/star/util/XModeSelector.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/beans/XIntrospection.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/extract.hxx>
+#include <comphelper/evtmethodhelper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/stl_types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/servicefactory.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/logfile.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/viewsh.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/color.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/shl.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/waitobj.hxx>
+#include <osl/mutex.hxx>
+
+#include <algorithm>
+#include <functional>
+
+// wird fuer Invalidate verwendet -> mitpflegen
+sal_uInt16 DatabaseSlotMap[] =
+{
+ SID_FM_RECORD_FIRST,
+ SID_FM_RECORD_NEXT,
+ SID_FM_RECORD_PREV,
+ SID_FM_RECORD_LAST,
+ SID_FM_RECORD_NEW,
+ SID_FM_RECORD_DELETE,
+ SID_FM_RECORD_ABSOLUTE,
+ SID_FM_RECORD_TOTAL,
+ SID_FM_RECORD_SAVE,
+ SID_FM_RECORD_UNDO,
+ SID_FM_REMOVE_FILTER_SORT,
+ SID_FM_SORTUP,
+ SID_FM_SORTDOWN,
+ SID_FM_ORDERCRIT,
+ SID_FM_AUTOFILTER,
+ SID_FM_FORM_FILTERED,
+ SID_FM_REFRESH,
+ SID_FM_REFRESH_FORM_CONTROL,
+ SID_FM_SEARCH,
+ SID_FM_FILTER_START,
+ SID_FM_VIEW_AS_GRID,
+ 0
+};
+
+// wird fuer Invalidate verwendet -> mitpflegen
+// aufsteigend sortieren !!!!!!
+sal_Int16 DlgSlotMap[] = // slots des Controllers
+{
+ SID_FM_CTL_PROPERTIES,
+ SID_FM_PROPERTIES,
+ SID_FM_TAB_DIALOG,
+ SID_FM_ADD_FIELD,
+ SID_FM_SHOW_FMEXPLORER,
+ SID_FM_FIELDS_CONTROL,
+ SID_FM_SHOW_PROPERTIES,
+ SID_FM_PROPERTY_CONTROL,
+ SID_FM_FMEXPLORER_CONTROL,
+ SID_FM_SHOW_DATANAVIGATOR,
+ SID_FM_DATANAVIGATOR_CONTROL,
+ 0
+};
+
+sal_Int16 SelObjectSlotMap[] = // vom SelObject abhaengige Slots
+{
+ SID_FM_CONVERTTO_EDIT,
+ SID_FM_CONVERTTO_BUTTON,
+ SID_FM_CONVERTTO_FIXEDTEXT,
+ SID_FM_CONVERTTO_LISTBOX,
+ SID_FM_CONVERTTO_CHECKBOX,
+ SID_FM_CONVERTTO_RADIOBUTTON,
+ SID_FM_CONVERTTO_GROUPBOX,
+ SID_FM_CONVERTTO_COMBOBOX,
+ SID_FM_CONVERTTO_IMAGEBUTTON,
+ SID_FM_CONVERTTO_FILECONTROL,
+ SID_FM_CONVERTTO_DATE,
+ SID_FM_CONVERTTO_TIME,
+ SID_FM_CONVERTTO_NUMERIC,
+ SID_FM_CONVERTTO_CURRENCY,
+ SID_FM_CONVERTTO_PATTERN,
+ SID_FM_CONVERTTO_IMAGECONTROL,
+ SID_FM_CONVERTTO_FORMATTED,
+ SID_FM_CONVERTTO_SCROLLBAR,
+ SID_FM_CONVERTTO_SPINBUTTON,
+ SID_FM_CONVERTTO_NAVIGATIONBAR,
+
+ SID_FM_FMEXPLORER_CONTROL,
+ SID_FM_DATANAVIGATOR_CONTROL,
+
+ 0
+};
+
+// die folgenden Arrays muessen kosistent sein, also einander entsprechende Eintraege an der selben relativen Position
+// innerhalb ihres jeweiligen Arrays stehen
+sal_Int16 nConvertSlots[] =
+{
+ SID_FM_CONVERTTO_EDIT,
+ SID_FM_CONVERTTO_BUTTON,
+ SID_FM_CONVERTTO_FIXEDTEXT,
+ SID_FM_CONVERTTO_LISTBOX,
+ SID_FM_CONVERTTO_CHECKBOX,
+ SID_FM_CONVERTTO_RADIOBUTTON,
+ SID_FM_CONVERTTO_GROUPBOX,
+ SID_FM_CONVERTTO_COMBOBOX,
+ SID_FM_CONVERTTO_IMAGEBUTTON,
+ SID_FM_CONVERTTO_FILECONTROL,
+ SID_FM_CONVERTTO_DATE,
+ SID_FM_CONVERTTO_TIME,
+ SID_FM_CONVERTTO_NUMERIC,
+ SID_FM_CONVERTTO_CURRENCY,
+ SID_FM_CONVERTTO_PATTERN,
+ SID_FM_CONVERTTO_IMAGECONTROL,
+ SID_FM_CONVERTTO_FORMATTED,
+ SID_FM_CONVERTTO_SCROLLBAR,
+ SID_FM_CONVERTTO_SPINBUTTON,
+ SID_FM_CONVERTTO_NAVIGATIONBAR
+};
+
+sal_Int16 nCreateSlots[] =
+{
+ SID_FM_EDIT,
+ SID_FM_PUSHBUTTON,
+ SID_FM_FIXEDTEXT,
+ SID_FM_LISTBOX,
+ SID_FM_CHECKBOX,
+ SID_FM_RADIOBUTTON,
+ SID_FM_GROUPBOX,
+ SID_FM_COMBOBOX,
+ SID_FM_IMAGEBUTTON,
+ SID_FM_FILECONTROL,
+ SID_FM_DATEFIELD,
+ SID_FM_TIMEFIELD,
+ SID_FM_NUMERICFIELD,
+ SID_FM_CURRENCYFIELD,
+ SID_FM_PATTERNFIELD,
+ SID_FM_IMAGECONTROL,
+ SID_FM_FORMATTEDFIELD,
+ SID_FM_SCROLLBAR,
+ SID_FM_SPINBUTTON,
+ SID_FM_NAVIGATIONBAR
+};
+
+sal_Int16 nObjectTypes[] =
+{
+ OBJ_FM_EDIT,
+ OBJ_FM_BUTTON,
+ OBJ_FM_FIXEDTEXT,
+ OBJ_FM_LISTBOX,
+ OBJ_FM_CHECKBOX,
+ OBJ_FM_RADIOBUTTON,
+ OBJ_FM_GROUPBOX,
+ OBJ_FM_COMBOBOX,
+ OBJ_FM_IMAGEBUTTON,
+ OBJ_FM_FILECONTROL,
+ OBJ_FM_DATEFIELD,
+ OBJ_FM_TIMEFIELD,
+ OBJ_FM_NUMERICFIELD,
+ OBJ_FM_CURRENCYFIELD,
+ OBJ_FM_PATTERNFIELD,
+ OBJ_FM_IMAGECONTROL,
+ OBJ_FM_FORMATTEDFIELD,
+ OBJ_FM_SCROLLBAR,
+ OBJ_FM_SPINBUTTON,
+ OBJ_FM_NAVIGATIONBAR
+};
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::ui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::form::binding;
+using namespace ::com::sun::star::form::runtime;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::script;
+using namespace ::svxform;
+using namespace ::svx;
+
+//==============================================================================
+//= helper
+//==============================================================================
+namespace
+{
+ //..........................................................................
+ void collectInterfacesFromMarkList( const SdrMarkList& _rMarkList, InterfaceBag& /* [out] */ _rInterfaces )
+ {
+ _rInterfaces.clear();
+
+ sal_uInt32 nMarkCount = _rMarkList.GetMarkCount();
+ for ( sal_uInt32 i = 0; i < nMarkCount; ++i)
+ {
+ SdrObject* pCurrent = _rMarkList.GetMark( i )->GetMarkedSdrObj();
+
+ SdrObjListIter* pGroupIterator = NULL;
+ if ( pCurrent->IsGroupObject() )
+ {
+ pGroupIterator = new SdrObjListIter( *pCurrent->GetSubList() );
+ pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : NULL;
+ }
+
+ while ( pCurrent )
+ {
+ FmFormObj* pAsFormObject = FmFormObj::GetFormObject( pCurrent );
+ // note this will de-reference virtual objects, if necessary/possible
+ if ( pAsFormObject )
+ {
+ Reference< XInterface > xControlModel( pAsFormObject->GetUnoControlModel(), UNO_QUERY );
+ // the UNO_QUERY is important for normalization
+ if ( xControlModel.is() )
+ _rInterfaces.insert( xControlModel );
+ }
+
+ // next element
+ pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : NULL;
+ }
+
+ if ( pGroupIterator )
+ delete pGroupIterator;
+ }
+ }
+
+ //..........................................................................
+ sal_Int16 GridView2ModelPos(const Reference< XIndexAccess>& rColumns, sal_Int16 nViewPos)
+ {
+ try
+ {
+ if (rColumns.is())
+ {
+ // loop through all columns
+ sal_Int16 i;
+ Reference< XPropertySet> xCur;
+ for (i=0; i<rColumns->getCount(); ++i)
+ {
+ rColumns->getByIndex(i) >>= xCur;
+ if (!::comphelper::getBOOL(xCur->getPropertyValue(FM_PROP_HIDDEN)))
+ {
+ // for every visible col : if nViewPos is greater zero, decrement it, else we
+ // have found the model position
+ if (!nViewPos)
+ break;
+ else
+ --nViewPos;
+ }
+ }
+ if (i<rColumns->getCount())
+ return i;
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return (sal_Int16)-1;
+ }
+
+ //..........................................................................
+ void TransferEventScripts(const Reference< XControlModel>& xModel, const Reference< XControl>& xControl,
+ const Sequence< ScriptEventDescriptor>& rTransferIfAvailable)
+ {
+ // first check if we have a XEventAttacherManager for the model
+ Reference< XChild> xModelChild(xModel, UNO_QUERY);
+ if (!xModelChild.is())
+ return; // nothing to do
+
+ Reference< XEventAttacherManager> xEventManager(xModelChild->getParent(), UNO_QUERY);
+ if (!xEventManager.is())
+ return; // nothing to do
+
+ if (!rTransferIfAvailable.getLength())
+ return; // nothing to do
+
+ // check for the index of the model within it's parent
+ Reference< XIndexAccess> xParentIndex(xModelChild->getParent(), UNO_QUERY);
+ if (!xParentIndex.is())
+ return; // nothing to do
+ sal_Int32 nIndex = getElementPos(xParentIndex, xModel);
+ if (nIndex<0 || nIndex>=xParentIndex->getCount())
+ return; // nothing to do
+
+ // then we need informations about the listeners supported by the control and the model
+ Sequence< Type> aModelListeners;
+ Sequence< Type> aControlListeners;
+
+ Reference< XIntrospection> xModelIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.Introspection"))), UNO_QUERY);
+ Reference< XIntrospection> xControlIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.Introspection"))), UNO_QUERY);
+
+ if (xModelIntrospection.is() && xModel.is())
+ {
+ Any aModel(makeAny(xModel));
+ aModelListeners = xModelIntrospection->inspect(aModel)->getSupportedListeners();
+ }
+
+ if (xControlIntrospection.is() && xControl.is())
+ {
+ Any aControl(makeAny(xControl));
+ aControlListeners = xControlIntrospection->inspect(aControl)->getSupportedListeners();
+ }
+
+ sal_Int32 nMaxNewLen = aModelListeners.getLength() + aControlListeners.getLength();
+ if (!nMaxNewLen)
+ return; // the model and the listener don't support any listeners (or we were unable to retrieve these infos)
+
+ Sequence< ScriptEventDescriptor> aTransferable(nMaxNewLen);
+ ScriptEventDescriptor* pTransferable = aTransferable.getArray();
+
+ const ScriptEventDescriptor* pCurrent = rTransferIfAvailable.getConstArray();
+ sal_Int32 i,j,k;
+ for (i=0; i<rTransferIfAvailable.getLength(); ++i, ++pCurrent)
+ {
+ // search the model/control idl classes for the event described by pCurrent
+ for ( Sequence< Type>* pCurrentArray = &aModelListeners;
+ pCurrentArray;
+ pCurrentArray = (pCurrentArray == &aModelListeners) ? &aControlListeners : NULL
+ )
+ {
+ const Type* pCurrentListeners = pCurrentArray->getConstArray();
+ for (j=0; j<pCurrentArray->getLength(); ++j, ++pCurrentListeners)
+ {
+ UniString aListener = (*pCurrentListeners).getTypeName();
+ xub_StrLen nTokens = aListener.GetTokenCount('.');
+ if (nTokens)
+ aListener = aListener.GetToken(nTokens - 1, '.');
+
+ if (aListener == pCurrent->ListenerType.getStr())
+ // the current ScriptEventDescriptor doesn't match the current listeners class
+ continue;
+
+ // now check the methods
+ Sequence< ::rtl::OUString> aMethodsNames = ::comphelper::getEventMethodsForType(*pCurrentListeners);
+
+ const ::rtl::OUString* pMethodsNames = aMethodsNames.getConstArray();
+ for (k=0; k<aMethodsNames.getLength(); ++k, ++pMethodsNames)
+ {
+ if ((*pMethodsNames).compareTo(pCurrent->EventMethod) != COMPARE_EQUAL)
+ // the current ScriptEventDescriptor doesn't match the current listeners current method
+ continue;
+
+ // we can transfer the script event : the model (control) supports it
+ *pTransferable = *pCurrent;
+ ++pTransferable;
+ break;
+ }
+ if (k<aMethodsNames.getLength())
+ break;
+ }
+ }
+ }
+
+ sal_Int32 nRealNewLen = pTransferable - aTransferable.getArray();
+ aTransferable.realloc(nRealNewLen);
+
+ xEventManager->registerScriptEvents(nIndex, aTransferable);
+ }
+
+ //------------------------------------------------------------------------------
+ ::rtl::OUString getServiceNameByControlType(sal_Int16 nType)
+ {
+ switch (nType)
+ {
+ case OBJ_FM_EDIT : return FM_COMPONENT_TEXTFIELD;
+ case OBJ_FM_BUTTON : return FM_COMPONENT_COMMANDBUTTON;
+ case OBJ_FM_FIXEDTEXT : return FM_COMPONENT_FIXEDTEXT;
+ case OBJ_FM_LISTBOX : return FM_COMPONENT_LISTBOX;
+ case OBJ_FM_CHECKBOX : return FM_COMPONENT_CHECKBOX;
+ case OBJ_FM_RADIOBUTTON : return FM_COMPONENT_RADIOBUTTON;
+ case OBJ_FM_GROUPBOX : return FM_COMPONENT_GROUPBOX;
+ case OBJ_FM_COMBOBOX : return FM_COMPONENT_COMBOBOX;
+ case OBJ_FM_GRID : return FM_COMPONENT_GRIDCONTROL;
+ case OBJ_FM_IMAGEBUTTON : return FM_COMPONENT_IMAGEBUTTON;
+ case OBJ_FM_FILECONTROL : return FM_COMPONENT_FILECONTROL;
+ case OBJ_FM_DATEFIELD : return FM_COMPONENT_DATEFIELD;
+ case OBJ_FM_TIMEFIELD : return FM_COMPONENT_TIMEFIELD;
+ case OBJ_FM_NUMERICFIELD : return FM_COMPONENT_NUMERICFIELD;
+ case OBJ_FM_CURRENCYFIELD : return FM_COMPONENT_CURRENCYFIELD;
+ case OBJ_FM_PATTERNFIELD : return FM_COMPONENT_PATTERNFIELD;
+ case OBJ_FM_HIDDEN : return FM_COMPONENT_HIDDENCONTROL;
+ case OBJ_FM_IMAGECONTROL : return FM_COMPONENT_IMAGECONTROL;
+ case OBJ_FM_FORMATTEDFIELD : return FM_COMPONENT_FORMATTEDFIELD;
+ case OBJ_FM_SCROLLBAR : return FM_SUN_COMPONENT_SCROLLBAR;
+ case OBJ_FM_SPINBUTTON : return FM_SUN_COMPONENT_SPINBUTTON;
+ case OBJ_FM_NAVIGATIONBAR : return FM_SUN_COMPONENT_NAVIGATIONBAR;
+ }
+ return ::rtl::OUString();
+ }
+
+}
+
+//------------------------------------------------------------------------------
+// check if the control has one of the interfaces we can use for searching
+// *_pCurrentText will be filled with the current text of the control (as used when searching this control)
+sal_Bool IsSearchableControl( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>& _rxControl,
+ ::rtl::OUString* _pCurrentText )
+{
+ if ( !_rxControl.is() )
+ return sal_False;
+
+ Reference< XTextComponent > xAsText( _rxControl, UNO_QUERY );
+ if ( xAsText.is() )
+ {
+ if ( _pCurrentText )
+ *_pCurrentText = xAsText->getText();
+ return sal_True;
+ }
+
+ Reference< XListBox > xListBox( _rxControl, UNO_QUERY );
+ if ( xListBox.is() )
+ {
+ if ( _pCurrentText )
+ *_pCurrentText = xListBox->getSelectedItem();
+ return sal_True;
+ }
+
+ Reference< XCheckBox > xCheckBox( _rxControl, UNO_QUERY );
+ if ( xCheckBox.is() )
+ {
+ if ( _pCurrentText )
+ {
+ switch ( (TriState)xCheckBox->getState() )
+ {
+ case STATE_NOCHECK: *_pCurrentText = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "0" )); break;
+ case STATE_CHECK: *_pCurrentText = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "1" )); break;
+ default: *_pCurrentText = ::rtl::OUString(); break;
+ }
+ }
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmXBoundFormFieldIterator::ShouldStepInto(const Reference< XInterface>& _rContainer) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXBoundFormFieldIterator::ShouldStepInto" );
+ if (_rContainer == m_xStartingPoint)
+ // would be quite stupid to step over the root ....
+ return sal_True;
+
+ return Reference< XControlModel>(_rContainer, UNO_QUERY).is();
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmXBoundFormFieldIterator::ShouldHandleElement(const Reference< XInterface>& _rElement)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXBoundFormFieldIterator::ShouldHandleElement" );
+ if (!_rElement.is())
+ // NULL element
+ return sal_False;
+
+ if (Reference< XForm>(_rElement, UNO_QUERY).is() || Reference< XGrid>(_rElement, UNO_QUERY).is())
+ // a forms or a grid
+ return sal_False;
+
+ Reference< XPropertySet> xSet(_rElement, UNO_QUERY);
+ if (!xSet.is() || !::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ // no "BoundField" property
+ return sal_False;
+
+ Any aVal( xSet->getPropertyValue(FM_PROP_BOUNDFIELD) );
+ if (aVal.getValueTypeClass() != TypeClass_INTERFACE)
+ // void or invalid property value
+ return sal_False;
+
+ return aVal.hasValue();
+}
+
+//------------------------------------------------------------------------------
+sal_Bool isControlList(const SdrMarkList& rMarkList)
+{
+ // enthaelt die liste nur Controls und mindestens ein control
+ sal_uInt32 nMarkCount = rMarkList.GetMarkCount();
+ sal_Bool bControlList = nMarkCount != 0;
+
+ sal_Bool bHadAnyLeafs = sal_False;
+
+ for (sal_uInt32 i = 0; i < nMarkCount && bControlList; i++)
+ {
+ SdrObject *pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
+ E3dObject* pAs3DObject = PTR_CAST(E3dObject, pObj);
+ // E3dObject's do not contain any 2D-objects (by definition)
+ // we need this extra check here : an E3dObject->IsGroupObject says "YES", but an SdrObjListIter working
+ // with an E3dObject doesn't give me any Nodes (E3dObject has a sub list, but no members in that list,
+ // cause there implementation differs from the one of "normal" SdrObject's. Unfortunally SdrObject::IsGroupObject
+ // doesn't check the element count of the sub list, which is simply a bug in IsGroupObject we can't fix at the moment).
+ // So at the end of this function bControlList would have the same value it was initialized with above : sal_True
+ // And this would be wrong :)
+ // 03.02.00 - 72529 - FS
+ if (!pAs3DObject)
+ {
+ if (pObj->IsGroupObject())
+ {
+ SdrObjListIter aIter(*pObj->GetSubList());
+ while (aIter.IsMore() && bControlList)
+ {
+ bControlList = FmFormInventor == aIter.Next()->GetObjInventor();
+ bHadAnyLeafs = sal_True;
+ }
+ }
+ else
+ {
+ bHadAnyLeafs = sal_True;
+ bControlList = FmFormInventor == pObj->GetObjInventor();
+ }
+ }
+ }
+
+ return bControlList && bHadAnyLeafs;
+}
+
+//------------------------------------------------------------------------
+Reference< XForm > GetForm(const Reference< XInterface>& _rxElement)
+{
+ Reference< XForm > xForm( _rxElement, UNO_QUERY );
+ if ( xForm.is() )
+ return xForm;
+
+ Reference< XChild > xChild( _rxElement, UNO_QUERY );
+ if ( xChild.is() )
+ return GetForm( xChild->getParent() );
+
+ return Reference< XForm >();
+}
+
+//========================================================================
+// class FmXFormShell_Base_Disambiguation
+//========================================================================
+FmXFormShell_Base_Disambiguation::FmXFormShell_Base_Disambiguation( ::osl::Mutex& _rMutex )
+ :FmXFormShell_BD_BASE( _rMutex )
+{
+}
+
+void SAL_CALL FmXFormShell_Base_Disambiguation::disposing()
+{
+ WeakComponentImplHelperBase::disposing();
+ // Note:
+ // This is a HACK.
+ // Normally it should be sufficient to call the "disposing" of our direct
+ // base class, but SUN PRO 5 does not like this and claims there is a conflict
+ // with the XEventListener::disposing(EventObject) of our various listener
+ // base classes.
+}
+
+//========================================================================
+// class FmXFormShell
+//========================================================================
+DBG_NAME(FmXFormShell);
+//------------------------------------------------------------------------
+FmXFormShell::FmXFormShell( FmFormShell& _rShell, SfxViewFrame* _pViewFrame )
+ :FmXFormShell_BASE(m_aMutex)
+ ,FmXFormShell_CFGBASE(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Misc")), CONFIG_MODE_DELAYED_UPDATE)
+ ,m_eNavigate( NavigationBarMode_NONE )
+ ,m_nInvalidationEvent( 0 )
+ ,m_nActivationEvent( 0 )
+ ,m_pShell( &_rShell )
+ ,m_pTextShell( new ::svx::FmTextControlShell( _pViewFrame ) )
+ ,m_aActiveControllerFeatures( ::comphelper::getProcessServiceFactory(), this )
+ ,m_aNavControllerFeatures( ::comphelper::getProcessServiceFactory(), this )
+ ,m_eDocumentType( eUnknownDocumentType )
+ ,m_nLockSlotInvalidation( 0 )
+ ,m_bHadPropertyBrowserInDesignMode( sal_False )
+ ,m_bTrackProperties( sal_True )
+ ,m_bUseWizards( sal_True )
+ ,m_bDatabaseBar( sal_False )
+ ,m_bInActivate( sal_False )
+ ,m_bSetFocus( sal_False )
+ ,m_bFilterMode( sal_False )
+ ,m_bChangingDesignMode( sal_False )
+ ,m_bPreparedClose( sal_False )
+ ,m_bFirstActivation( sal_True )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::FmXFormShell" );
+ DBG_CTOR(FmXFormShell,NULL);
+ m_aMarkTimer.SetTimeout(100);
+ m_aMarkTimer.SetTimeoutHdl(LINK(this,FmXFormShell,OnTimeOut));
+
+ if ( _pViewFrame )
+ m_xAttachedFrame = _pViewFrame->GetFrame().GetFrameInterface();
+
+ // to prevent deletion of this we acquire our refcounter once
+ ::comphelper::increment(FmXFormShell_BASE::m_refCount);
+
+ // correct the refcounter
+ ::comphelper::decrement(FmXFormShell_BASE::m_refCount);
+
+ // cache the current configuration settings we're interested in
+ implAdjustConfigCache();
+ // and register for changes on this settings
+ Sequence< ::rtl::OUString > aNames(1);
+ aNames[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FormControlPilotsEnabled"));
+ EnableNotification(aNames);
+}
+
+//------------------------------------------------------------------------
+FmXFormShell::~FmXFormShell()
+{
+ delete m_pTextShell;
+ DBG_DTOR(FmXFormShell,NULL);
+}
+
+//------------------------------------------------------------------
+Reference< XModel > FmXFormShell::getContextDocument() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getContextDocument" );
+ Reference< XModel > xModel;
+
+ // determine the type of document we live in
+ try
+ {
+ Reference< XController > xController;
+ if ( m_xAttachedFrame.is() )
+ xController = m_xAttachedFrame->getController();
+ if ( xController.is() )
+ xModel = xController->getModel();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return xModel;
+}
+
+//------------------------------------------------------------------
+bool FmXFormShell::isEnhancedForm() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::isEnhancedForm" );
+ return getDocumentType() == eEnhancedForm;
+}
+
+//------------------------------------------------------------------
+bool FmXFormShell::impl_checkDisposed() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::impl_checkDisposed" );
+ if ( !m_pShell )
+ {
+ OSL_ENSURE( false, "FmXFormShell::impl_checkDisposed: already disposed!" );
+ return true;
+ }
+ return false;
+}
+
+//------------------------------------------------------------------
+::svxform::DocumentType FmXFormShell::getDocumentType() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getDocumentType" );
+ if ( m_eDocumentType != eUnknownDocumentType )
+ return m_eDocumentType;
+
+ // determine the type of document we live in
+ Reference< XModel > xModel = getContextDocument();
+ if ( xModel.is() )
+ m_eDocumentType = DocumentClassification::classifyDocument( xModel );
+ else
+ {
+ OSL_ENSURE( sal_False, "FmXFormShell::getDocumentType: can't determine the document type!" );
+ m_eDocumentType = eTextDocument;
+ // fallback, just to have a defined state
+ }
+
+ return m_eDocumentType;
+}
+
+//------------------------------------------------------------------
+bool FmXFormShell::IsReadonlyDoc() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::IsReadonlyDoc" );
+ if ( impl_checkDisposed() )
+ return true;
+
+ FmFormModel* pModel = m_pShell->GetFormModel();
+ if ( pModel && pModel->GetObjectShell() )
+ return pModel->GetObjectShell()->IsReadOnly() || pModel->GetObjectShell()->IsReadOnlyUI();
+ return true;
+}
+
+//------------------------------------------------------------------
+Any SAL_CALL FmXFormShell::queryInterface( const Type& type) throw ( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::queryInterface" );
+ return FmXFormShell_BASE::queryInterface(type);
+}
+//------------------------------------------------------------------------------
+Sequence< Type > SAL_CALL FmXFormShell::getTypes( ) throw(RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getTypes" );
+ return FmXFormShell_BASE::getTypes();
+}
+//------------------------------------------------------------------------------
+Sequence< sal_Int8 > SAL_CALL FmXFormShell::getImplementationId() throw(RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getImplementationId" );
+ static ::cppu::OImplementationId* pId = 0;
+ if (! pId)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if (! pId)
+ {
+ static ::cppu::OImplementationId aId;
+ pId = &aId;
+ }
+ }
+ return pId->getImplementationId();
+}
+// EventListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormShell::disposing(const EventObject& e) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::disposing" );
+ impl_checkDisposed();
+
+ if (m_xActiveController == e.Source)
+ {
+ // wird der Controller freigeben dann alles loslassen
+ stopListening();
+ m_xActiveForm = NULL;
+ m_xActiveController = NULL;
+ m_xNavigationController = NULL;
+
+ m_aActiveControllerFeatures.dispose();
+ m_aNavControllerFeatures.dispose();
+
+ if ( m_pShell )
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
+ }
+
+ if (e.Source == m_xExternalViewController)
+ {
+ Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY );
+ OSL_ENSURE( xFormController.is(), "FmXFormShell::disposing: invalid external view controller!" );
+ if (xFormController.is())
+ xFormController->removeActivateListener((XFormControllerListener*)this);
+
+ Reference< ::com::sun::star::lang::XComponent> xComp(m_xExternalViewController, UNO_QUERY);
+ if (xComp.is())
+ xComp->removeEventListener((XEventListener*)(XPropertyChangeListener*)this);
+
+ m_xExternalViewController = NULL;
+ m_xExternalDisplayedForm = NULL;
+ m_xExtViewTriggerController = NULL;
+
+ InvalidateSlot( SID_FM_VIEW_AS_GRID, sal_False );
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormShell::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::propertyChange" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if (evt.PropertyName == FM_PROP_ROWCOUNT)
+ {
+ // Das gleich folgenden Update erzwingt ein Neu-Painten der entsprechenden Slots. Wenn ich mich aber hier nicht
+ // in dem HauptThread der Applikation befinde (weil zum Beispiel ein Cursor gerade Datensaetze zaehlt und mir dabei
+ // immer diese PropertyChanges beschert), kann sich das mit en normalen Paints im HauptThread der Applikation beissen.
+ // (Solche Paints passieren zum Beispiel, wenn man einfach nur eine andere Applikation ueber das Office legt und wieder
+ // zurueckschaltet).
+ // Deshalb die Benutzung des SolarMutex, der sichert das ab.
+ ::osl::SolarMutex& rSolarSafety = Application::GetSolarMutex();
+ if (rSolarSafety.tryToAcquire())
+ {
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_RECORD_TOTAL , sal_True, sal_False);
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(SID_FM_RECORD_TOTAL);
+ rSolarSafety.release();
+ }
+ else
+ {
+ // with the following the slot is invalidated asynchron
+ LockSlotInvalidation(sal_True);
+ InvalidateSlot(SID_FM_RECORD_TOTAL, sal_False);
+ LockSlotInvalidation(sal_False);
+ }
+ }
+
+ // this may be called from a non-main-thread so invalidate the shell asynchronously
+ LockSlotInvalidation(sal_True);
+ InvalidateSlot(0, 0); // special meaning : invalidate m_pShell
+ LockSlotInvalidation(sal_False);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::invalidateFeatures( const ::std::vector< sal_Int32 >& _rFeatures )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::invalidateFeatures" );
+ if ( impl_checkDisposed() )
+ return;
+
+ OSL_ENSURE( _rFeatures.size() > 0, "FmXFormShell::invalidateFeatures: invalid arguments!" );
+
+ if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() )
+ {
+ // unfortunately, SFX requires sal_uInt16
+ ::std::vector< sal_uInt16 > aSlotIds;
+ aSlotIds.reserve( _rFeatures.size() );
+ ::std::copy( _rFeatures.begin(),
+ _rFeatures.end(),
+ ::std::insert_iterator< ::std::vector< sal_uInt16 > >( aSlotIds, aSlotIds.begin() )
+ );
+
+ // furthermore, SFX wants a terminating 0
+ aSlotIds.push_back( 0 );
+
+ // and, last but not least, SFX wants the ids to be sorted
+ ::std::sort( aSlotIds.begin(), aSlotIds.end() - 1 );
+
+ sal_uInt16 *pSlotIds = aSlotIds.empty() ? 0 : &(aSlotIds[0]);
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( pSlotIds );
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormShell::formActivated(const EventObject& rEvent) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::formActivated" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW );
+ m_pTextShell->formActivated( xController );
+ setActiveController( xController );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormShell::formDeactivated(const EventObject& rEvent) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::formDeactivated" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW );
+ m_pTextShell->formDeactivated( xController );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::disposing()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::disposing" );
+ impl_checkDisposed();
+
+ FmXFormShell_BASE::disposing();
+
+ if ( m_pShell && !m_pShell->IsDesignMode() )
+ setActiveController( NULL, sal_True );
+ // do NOT save the content of the old form (the second parameter tells this)
+ // if we're here, then we expect that PrepareClose has been called, and thus the user
+ // got a chance to commit or reject any changes. So in case we're here and there
+ // are still uncommitted changes, the user explicitly wanted this.
+ // 2002-11-11 - 104702 - fs@openoffice.org
+
+ m_pTextShell->dispose();
+
+ m_xAttachedFrame = NULL;
+
+ CloseExternalFormViewer();
+
+ while ( m_aLoadingPages.size() )
+ {
+ Application::RemoveUserEvent( m_aLoadingPages.front().nEventId );
+ m_aLoadingPages.pop();
+ }
+
+ {
+ ::osl::MutexGuard aGuard(m_aInvalidationSafety);
+ if (m_nInvalidationEvent)
+ {
+ Application::RemoveUserEvent(m_nInvalidationEvent);
+ m_nInvalidationEvent = 0;
+ }
+ if ( m_nActivationEvent )
+ {
+ Application::RemoveUserEvent( m_nActivationEvent );
+ m_nActivationEvent = 0;
+ }
+ }
+
+ {
+ ::osl::ClearableMutexGuard aGuard(m_aAsyncSafety);
+ aGuard.clear();
+
+ DBG_ASSERT(!m_nInvalidationEvent, "FmXFormShell::~FmXFormShell : still have an invalidation event !");
+ // should habe been deleted while beeing disposed
+
+ m_aMarkTimer.Stop();
+ }
+
+ DisableNotification();
+
+ RemoveElement( m_xForms );
+ m_xForms.clear();
+
+ impl_switchActiveControllerListening( false );
+ m_xActiveController = NULL;
+ m_xActiveForm = NULL;
+
+ m_pShell = NULL;
+ m_xNavigationController = NULL;
+ m_xCurrentForm = NULL;
+ m_xLastGridFound = NULL;
+ m_xAttachedFrame = NULL;
+ m_xExternalViewController = NULL;
+ m_xExtViewTriggerController = NULL;
+ m_xExternalDisplayedForm = NULL;
+ m_xLastGridFound = NULL;
+
+ InterfaceBag aEmpty;
+ m_aCurrentSelection.swap( aEmpty );
+
+ m_aActiveControllerFeatures.dispose();
+ m_aNavControllerFeatures.dispose();
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::UpdateSlot( sal_Int16 _nId )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::UpdateSlot" );
+ if ( impl_checkDisposed() )
+ return;
+
+ ::osl::MutexGuard aGuard(m_aInvalidationSafety);
+
+ if ( m_nLockSlotInvalidation )
+ {
+ OSL_ENSURE( sal_False, "FmXFormShell::UpdateSlot: cannot update if invalidation is currently locked!" );
+ InvalidateSlot( _nId, sal_False );
+ }
+ else
+ {
+ OSL_ENSURE( _nId, "FmXFormShell::UpdateSlot: can't update the complete shell!" );
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( _nId, sal_True, sal_True );
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update( _nId );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::InvalidateSlot( sal_Int16 nId, sal_Bool bWithId )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::InvalidateSlot" );
+ if ( impl_checkDisposed() )
+ return;
+
+ ::osl::MutexGuard aGuard(m_aInvalidationSafety);
+ if (m_nLockSlotInvalidation)
+ {
+ m_arrInvalidSlots.Insert(nId, m_arrInvalidSlots.Count());
+ BYTE nFlags = ( bWithId ? 0x01 : 0 );
+ m_arrInvalidSlots_Flags.Insert(nFlags, m_arrInvalidSlots_Flags.Count());
+ }
+ else
+ if (nId)
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(nId, sal_True, bWithId);
+ else
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::LockSlotInvalidation(sal_Bool bLock)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::LockSlotInvalidation" );
+ if ( impl_checkDisposed() )
+ return;
+
+ ::osl::MutexGuard aGuard(m_aInvalidationSafety);
+ DBG_ASSERT(bLock || m_nLockSlotInvalidation>0, "FmXFormShell::LockSlotInvalidation : invalid call !");
+
+ if (bLock)
+ ++m_nLockSlotInvalidation;
+ else if (!--m_nLockSlotInvalidation)
+ {
+ // alles, was sich waehrend der gelockten Phase angesammelt hat, (asynchron) invalidieren
+ if (!m_nInvalidationEvent)
+ m_nInvalidationEvent = Application::PostUserEvent(LINK(this, FmXFormShell, OnInvalidateSlots));
+ }
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormShell, OnInvalidateSlots, void*, EMPTYARG)
+{
+ if ( impl_checkDisposed() )
+ return 0L;
+
+ ::osl::MutexGuard aGuard(m_aInvalidationSafety);
+ m_nInvalidationEvent = 0;
+
+ DBG_ASSERT(m_arrInvalidSlots.Count() == m_arrInvalidSlots_Flags.Count(),
+ "FmXFormShell::OnInvalidateSlots : inconsistent slot arrays !");
+ BYTE nFlags;
+ for (sal_Int16 i=0; i<m_arrInvalidSlots.Count(); ++i)
+ {
+ nFlags = m_arrInvalidSlots_Flags[i];
+
+ if (m_arrInvalidSlots[i])
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(m_arrInvalidSlots[i], sal_True, (nFlags & 0x01));
+ else
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
+ }
+
+ m_arrInvalidSlots.Remove(0, m_arrInvalidSlots.Count());
+ m_arrInvalidSlots_Flags.Remove(0, m_arrInvalidSlots_Flags.Count());
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::ForceUpdateSelection(sal_Bool bAllowInvalidation)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ForceUpdateSelection" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if (IsSelectionUpdatePending())
+ {
+ m_aMarkTimer.Stop();
+
+ // die Invalidierung der Slots, die implizit von SetSelection besorgt wird, eventuell abschalten
+ if (!bAllowInvalidation)
+ LockSlotInvalidation(sal_True);
+
+ SetSelection(m_pShell->GetFormView()->GetMarkedObjectList());
+
+ if (!bAllowInvalidation)
+ LockSlotInvalidation(sal_False);
+ }
+}
+
+//------------------------------------------------------------------------------
+PopupMenu* FmXFormShell::GetConversionMenu()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::GetConversionMenu" );
+
+ PopupMenu* pNewMenu = new PopupMenu(SVX_RES( RID_FMSHELL_CONVERSIONMENU ));
+
+ ImageList aImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL) );
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( nConvertSlots ); ++i )
+ {
+ // das entsprechende Image dran
+ pNewMenu->SetItemImage(nConvertSlots[i], aImageList.GetImage(nCreateSlots[i]));
+ }
+
+ return pNewMenu;
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::isControlConversionSlot( sal_uInt16 nSlotId )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::isControlConversionSlot" );
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( nConvertSlots ); ++i )
+ if (nConvertSlots[i] == nSlotId)
+ return true;
+ return false;
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::executeControlConversionSlot( sal_uInt16 _nSlotId )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::executeControlConversionSlot" );
+ OSL_PRECOND( canConvertCurrentSelectionToControl( _nSlotId ), "FmXFormShell::executeControlConversionSlot: illegal call!" );
+ InterfaceBag::const_iterator aSelectedElement = m_aCurrentSelection.begin();
+ if ( aSelectedElement == m_aCurrentSelection.end() )
+ return false;
+
+ return executeControlConversionSlot( Reference< XFormComponent >( *aSelectedElement, UNO_QUERY ), _nSlotId );
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::executeControlConversionSlot( const Reference< XFormComponent >& _rxObject, sal_uInt16 _nSlotId )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::executeControlConversionSlot" );
+ if ( impl_checkDisposed() )
+ return false;
+
+ OSL_ENSURE( _rxObject.is(), "FmXFormShell::executeControlConversionSlot: invalid object!" );
+ if ( !_rxObject.is() )
+ return false;
+
+ SdrPage* pPage = m_pShell->GetCurPage();
+ FmFormPage* pFormPage = pPage ? dynamic_cast< FmFormPage* >( pPage ) : NULL;
+ OSL_ENSURE( pFormPage, "FmXFormShell::executeControlConversionSlot: no current (form) page!" );
+ if ( !pFormPage )
+ return false;
+
+ OSL_ENSURE( isSolelySelected( _rxObject ),
+ "FmXFormShell::executeControlConversionSlot: hmm ... shouldn't this parameter be redundant?" );
+
+ for ( size_t lookupSlot = 0; lookupSlot < SAL_N_ELEMENTS( nConvertSlots ); ++lookupSlot )
+ {
+ if (nConvertSlots[lookupSlot] == _nSlotId)
+ {
+ Reference< XInterface > xNormalizedObject( _rxObject, UNO_QUERY );
+
+ FmFormObj* pFormObject = NULL;
+ SdrObjListIter aPageIter( *pFormPage );
+ while ( aPageIter.IsMore() )
+ {
+ SdrObject* pCurrent = aPageIter.Next();
+ pFormObject = FmFormObj::GetFormObject( pCurrent );
+ if ( !pFormObject )
+ continue;
+
+ Reference< XInterface > xCurrentNormalized( pFormObject->GetUnoControlModel(), UNO_QUERY );
+ if ( xCurrentNormalized.get() == xNormalizedObject.get() )
+ break;
+
+ pFormObject = NULL;
+ }
+
+ if ( !pFormObject )
+ return false;
+
+ ::rtl::OUString sNewName( getServiceNameByControlType( nObjectTypes[ lookupSlot ] ) );
+ Reference< XControlModel> xNewModel( ::comphelper::getProcessServiceFactory()->createInstance( sNewName ), UNO_QUERY );
+ if (!xNewModel.is())
+ return false;
+
+ Reference< XControlModel> xOldModel( pFormObject->GetUnoControlModel() );
+ Reference< XServiceInfo> xModelInfo(xOldModel, UNO_QUERY);
+
+ // Properties uebertragen
+ Reference< XPropertySet> xOldSet(xOldModel, UNO_QUERY);
+ Reference< XPropertySet> xNewSet(xNewModel, UNO_QUERY);
+
+
+ Locale aNewLanguage = Application::GetSettings().GetUILocale();
+ TransferFormComponentProperties(xOldSet, xNewSet, aNewLanguage);
+
+ Sequence< ::com::sun::star::script::ScriptEventDescriptor> aOldScripts;
+ Reference< XChild> xChild(xOldModel, UNO_QUERY);
+ if (xChild.is())
+ {
+ Reference< XIndexAccess> xParent(xChild->getParent(), UNO_QUERY);
+
+ // remember old script events
+ Reference< ::com::sun::star::script::XEventAttacherManager> xEvManager(xChild->getParent(), UNO_QUERY);
+ if (xParent.is() && xEvManager.is())
+ {
+ sal_Int32 nIndex = getElementPos(xParent, xOldModel);
+ if (nIndex>=0 && nIndex<xParent->getCount())
+ aOldScripts = xEvManager->getScriptEvents(nIndex);
+ }
+
+ // replace the mdoel within the parent container
+ Reference< XIndexContainer> xIndexParent(xChild->getParent(), UNO_QUERY);
+ if (xIndexParent.is())
+ {
+ // the form container works with FormComponents
+ Reference< XFormComponent> xComponent(xNewModel, UNO_QUERY);
+ DBG_ASSERT(xComponent.is(), "FmXFormShell::executeControlConversionSlot: the new model is no form component !");
+ Any aNewModel(makeAny(xComponent));
+ try
+ {
+
+ sal_Int32 nIndex = getElementPos(xParent, xOldModel);
+ if (nIndex>=0 && nIndex<xParent->getCount())
+ xIndexParent->replaceByIndex(nIndex, aNewModel);
+ else
+ {
+ DBG_ERROR("FmXFormShell::executeControlConversionSlot: could not replace the model !");
+ Reference< ::com::sun::star::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY);
+ if (xNewComponent.is())
+ xNewComponent->dispose();
+ return false;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmXFormShell::executeControlConversionSlot: could not replace the model !");
+ Reference< ::com::sun::star::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY);
+ if (xNewComponent.is())
+ xNewComponent->dispose();
+ return false;
+ }
+
+ }
+ }
+
+ // special handling for the LabelControl-property : can only be set when the model is placed
+ // within the forms hierarchy
+ if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xOldSet) && ::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xNewSet))
+ {
+ try
+ {
+ xNewSet->setPropertyValue(FM_PROP_CONTROLLABEL, xOldSet->getPropertyValue(FM_PROP_CONTROLLABEL));
+ }
+ catch(Exception&)
+ {
+ }
+
+ }
+
+ // neues Model setzen
+ pFormObject->SetChanged();
+ pFormObject->SetUnoControlModel(xNewModel);
+
+ // transfer script events
+ // (do this _after_ SetUnoControlModel as we need the new (implicitly created) control)
+ if (aOldScripts.getLength())
+ {
+ // das Control zum Model suchen
+ Reference< XControlContainer > xControlContainer( getControlContainerForView() );
+
+ Sequence< Reference< XControl> > aControls( xControlContainer->getControls() );
+ const Reference< XControl>* pControls = aControls.getConstArray();
+
+ sal_uInt32 nLen = aControls.getLength();
+ Reference< XControl> xControl;
+ for (sal_uInt32 i=0 ; i<nLen; ++i)
+ {
+ if (pControls[i]->getModel() == xNewModel)
+ {
+ xControl = pControls[i];
+ break;
+ }
+ }
+ TransferEventScripts(xNewModel, xControl, aOldScripts);
+ }
+
+ // transfer value bindings, if possible
+ {
+ Reference< XBindableValue > xOldBindable( xOldModel, UNO_QUERY );
+ Reference< XBindableValue > xNewBindable( xNewModel, UNO_QUERY );
+ if ( xOldBindable.is() )
+ {
+ try
+ {
+ if ( xNewBindable.is() )
+ xNewBindable->setValueBinding( xOldBindable->getValueBinding() );
+ xOldBindable->setValueBinding( NULL );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ // same for list entry sources
+ {
+ Reference< XListEntrySink > xOldSink( xOldModel, UNO_QUERY );
+ Reference< XListEntrySink > xNewSink( xNewModel, UNO_QUERY );
+ if ( xOldSink.is() )
+ {
+ try
+ {
+ if ( xNewSink.is() )
+ xNewSink->setListEntrySource( xOldSink->getListEntrySource() );
+ xOldSink->setListEntrySource( NULL );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+
+ // create an undo action
+ FmFormModel* pModel = m_pShell->GetFormModel();
+ DBG_ASSERT(pModel != NULL, "FmXFormShell::executeControlConversionSlot: my shell has no model !");
+ if (pModel && pModel->IsUndoEnabled() )
+ {
+ pModel->AddUndo(new FmUndoModelReplaceAction(*pModel, pFormObject, xOldModel));
+ }
+ else
+ {
+ FmUndoModelReplaceAction::DisposeElement( xOldModel );
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::canConvertCurrentSelectionToControl( sal_Int16 nConversionSlot )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::canConvertCurrentSelectionToControl" );
+ if ( m_aCurrentSelection.empty() )
+ return false;
+
+ InterfaceBag::const_iterator aCheck = m_aCurrentSelection.begin();
+ Reference< XServiceInfo > xElementInfo( *aCheck, UNO_QUERY );
+ if ( !xElementInfo.is() )
+ // no service info -> cannot determine this
+ return false;
+
+ if ( ++aCheck != m_aCurrentSelection.end() )
+ // more than one element
+ return false;
+
+ if ( Reference< XForm >::query( xElementInfo ).is() )
+ // it's a form
+ return false;
+
+ sal_Int16 nObjectType = getControlTypeByObject( xElementInfo );
+
+ if ( ( OBJ_FM_HIDDEN == nObjectType )
+ || ( OBJ_FM_CONTROL == nObjectType )
+ || ( OBJ_FM_GRID == nObjectType )
+ )
+ return false; // those types cannot be converted
+
+ DBG_ASSERT(SAL_N_ELEMENTS(nConvertSlots) == SAL_N_ELEMENTS(nObjectTypes),
+ "FmXFormShell::canConvertCurrentSelectionToControl: nConvertSlots & nObjectTypes must have the same size !");
+
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( nConvertSlots ); ++i )
+ if (nConvertSlots[i] == nConversionSlot)
+ return nObjectTypes[i] != nObjectType;
+
+ return sal_True; // all other slots: assume "yes"
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::checkControlConversionSlotsForCurrentSelection( Menu& rMenu )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::checkControlConversionSlotsForCurrentSelection" );
+ for (sal_Int16 i=0; i<rMenu.GetItemCount(); ++i)
+ // der Context ist schon von einem Typ, der dem Eitnrag entspricht -> disable
+ rMenu.EnableItem( rMenu.GetItemId(i), canConvertCurrentSelectionToControl( rMenu.GetItemId( i ) ) );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::LoopGrids(sal_Int16 nWhat)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::LoopGrids" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XIndexContainer> xControlModels(m_xActiveForm, UNO_QUERY);
+ if (xControlModels.is())
+ {
+ for (sal_Int16 i=0; i<xControlModels->getCount(); ++i)
+ {
+ Reference< XPropertySet> xModelSet;
+ xControlModels->getByIndex(i) >>= xModelSet;
+ if (!xModelSet.is())
+ continue;
+
+ if (!::comphelper::hasProperty(FM_PROP_CLASSID, xModelSet))
+ continue;
+ sal_Int16 nClassId = ::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_CLASSID));
+ if (FormComponentType::GRIDCONTROL != nClassId)
+ continue;
+
+ if (!::comphelper::hasProperty(FM_PROP_CURSORCOLOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_ALWAYSSHOWCURSOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_DISPLAYSYNCHRON, xModelSet))
+ continue;
+
+ switch (nWhat & GA_SYNC_MASK)
+ {
+ case GA_DISABLE_SYNC:
+ {
+ sal_Bool bB(sal_False);
+ xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType()));
+ }
+ break;
+ case GA_FORCE_SYNC:
+ {
+ Any aOldVal( xModelSet->getPropertyValue(FM_PROP_DISPLAYSYNCHRON) );
+ sal_Bool bB(sal_True);
+ xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType()));
+ xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, aOldVal);
+ }
+ break;
+ case GA_ENABLE_SYNC:
+ {
+ sal_Bool bB(sal_True);
+ xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType()));
+ }
+ break;
+ }
+
+ if (nWhat & GA_DISABLE_ROCTRLR)
+ {
+ sal_Bool bB(sal_False);
+ xModelSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, Any(&bB,getBooleanCppuType()));
+ Reference< XPropertyState> xModelPropState(xModelSet, UNO_QUERY);
+ if (xModelPropState.is())
+ xModelPropState->setPropertyToDefault(FM_PROP_CURSORCOLOR);
+ else
+ xModelSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any()); // this should be the default
+ }
+ else if (nWhat & GA_ENABLE_ROCTRLR)
+ {
+ sal_Bool bB(sal_True);
+ xModelSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, Any(&bB,getBooleanCppuType()));
+ xModelSet->setPropertyValue(FM_PROP_CURSORCOLOR, makeAny(sal_Int32(COL_LIGHTRED)));
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XControlContainer > FmXFormShell::getControlContainerForView()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getControlContainerForView" );
+ if ( impl_checkDisposed() )
+ return NULL;
+
+ SdrPageView* pPageView = NULL;
+ if ( m_pShell && m_pShell->GetFormView() )
+ pPageView = m_pShell->GetFormView()->GetSdrPageView();
+
+ Reference< XControlContainer> xControlContainer;
+ if ( pPageView )
+ xControlContainer = pPageView->GetPageWindow(0)->GetControlContainer();
+
+ return xControlContainer;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::ExecuteTabOrderDialog( const Reference< XTabControllerModel >& _rxForForm )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ExecuteTabOrderDialog" );
+ if ( impl_checkDisposed() )
+ return;
+
+ OSL_PRECOND( _rxForForm.is(), "FmXFormShell::ExecuteTabOrderDialog: invalid tabbing model!" );
+ if ( !_rxForForm.is() )
+ return;
+
+ try
+ {
+ Sequence< Any > aDialogArgs( 3 );
+ aDialogArgs[0] <<= NamedValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TabbingModel" ) ),
+ makeAny( _rxForForm )
+ );
+ aDialogArgs[1] <<= NamedValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlContext" ) ),
+ makeAny( getControlContainerForView() )
+ );
+
+ Reference< XWindow > xParentWindow;
+ if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() )
+ xParentWindow = VCLUnoHelper::GetInterface ( &m_pShell->GetViewShell()->GetViewFrame()->GetWindow() );
+ aDialogArgs[2] <<= NamedValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ) ),
+ makeAny( xParentWindow )
+ );
+
+ Reference< dialogs::XExecutableDialog > xDialog(
+ ::comphelper::getProcessServiceFactory()->createInstanceWithArguments(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.ui.TabOrderDialog" ) ),
+ aDialogArgs
+ ),
+ UNO_QUERY
+ );
+ OSL_ENSURE( xDialog.is(), "FmXFormShell::ExecuteTabOrderDialog: could not create the dialog!" );
+
+ if ( xDialog.is() )
+ xDialog->execute();
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmXFormShell::ExecuteTabOrderDialog: caught an exception!" );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::ExecuteSearch()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ExecuteSearch" );
+ if ( impl_checkDisposed() )
+ return;
+
+ // eine Sammlung aller (logischen) Formulare
+ FmFormArray aEmpty;
+ m_aSearchForms.swap( aEmpty );
+ ::std::vector< String > aContextNames;
+ impl_collectFormSearchContexts_nothrow( m_pShell->GetCurPage()->GetForms(), ::rtl::OUString(), m_aSearchForms, aContextNames );
+ OSL_POSTCOND( m_aSearchForms.size() == aContextNames.size(),
+ "FmXFormShell::ExecuteSearch: nonsense!" );
+ if ( m_aSearchForms.size() != aContextNames.size() )
+ return;
+
+ // filter out the forms which do not contain valid controls at all
+ {
+ FmFormArray aValidForms;
+ ::std::vector< String > aValidContexts;
+ FmFormArray::const_iterator form = m_aSearchForms.begin();
+ ::std::vector< String >::const_iterator contextName = aContextNames.begin();
+ for ( ; form != m_aSearchForms.end(); ++form, ++contextName )
+ {
+ FmSearchContext aTestContext;
+ aTestContext.nContext = static_cast< sal_Int16 >( form - m_aSearchForms.begin() );
+ sal_uInt32 nValidControls = OnSearchContextRequest( &aTestContext );
+ if ( nValidControls > 0 )
+ {
+ aValidForms.push_back( *form );
+ aValidContexts.push_back( *contextName );
+ }
+ }
+
+ m_aSearchForms.swap( aValidForms );
+ aContextNames.swap( aValidContexts );
+ }
+
+ if (m_aSearchForms.size() == 0)
+ { // es gibt keine Controls, die alle Bedingungen fuer eine Suche erfuellen
+ ErrorBox(NULL, WB_OK, SVX_RESSTR(RID_STR_NODATACONTROLS)).Execute();
+ return;
+ }
+
+ // jetzt brauche ich noch einen 'initial context'
+ sal_Int16 nInitialContext = 0;
+ Reference< XForm> xActiveForm( getActiveForm());
+ for ( size_t i=0; i<m_aSearchForms.size(); ++i )
+ {
+ if (m_aSearchForms.at(i) == xActiveForm)
+ {
+ nInitialContext = (sal_Int16)i;
+ break;
+ }
+ }
+
+ // wenn der Dialog initial den Text des aktiven Controls anbieten soll, muss dieses ein XTextComponent-Interface habe,
+ // ausserdem macht das nur Sinn, wenn das aktuelle Feld auch an ein Tabellen- (oder was-auch-immer-)Feld gebunden ist
+ UniString strActiveField;
+ UniString strInitialText;
+ // ... das bekomme ich von meinem FormController
+ DBG_ASSERT(m_xActiveController.is(), "FmXFormShell::ExecuteSearch : no active controller !");
+ Reference< XControl> xActiveControl( m_xActiveController->getCurrentControl());
+ if (xActiveControl.is())
+ {
+ // das Control kann mir sein Model sagen ...
+ Reference< XControlModel> xActiveModel( xActiveControl->getModel());
+ DBG_ASSERT(xActiveModel.is(), "FmXFormShell::ExecuteSearch : active control has no model !");
+
+ // das Model frage ich nach der ControlSource-Eigenschaft ...
+ Reference< XPropertySet> xProperties(xActiveControl->getModel(), UNO_QUERY);
+ if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xProperties) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xProperties))
+ {
+ Reference< XPropertySet> xField;
+ xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+ if (xField.is()) // (nur wenn das Ding wirklich gebunden ist)
+ {
+ // und das Control selber nach einem TextComponent-Interface (damit ich mir dort den Text abholen kann)
+ Reference< XTextComponent> xText(xActiveControl, UNO_QUERY);
+ if (xText.is())
+ {
+ strActiveField = getLabelName(xProperties).getStr();
+ strInitialText = xText->getText().getStr();
+ }
+ }
+ }
+ else
+ {
+ // das Control selber hat keine ControlSource, aber vielleicht ist es ein GridControl
+ Reference< XGrid> xGrid(xActiveControl, UNO_QUERY);
+ if (xGrid.is())
+ {
+ // fuer strActiveField brauche ich die die ControlSource der Column, dafuer den Columns-Container, dafuer die
+ // GridPeer
+ Reference< XGridPeer> xGridPeer(xActiveControl->getPeer(), UNO_QUERY);
+ Reference< XIndexAccess> xColumns;
+ if (xGridPeer.is())
+ xColumns = Reference< XIndexAccess>(xGridPeer->getColumns(),UNO_QUERY);
+
+ sal_Int16 nViewCol = xGrid->getCurrentColumnPosition();
+ sal_Int16 nModelCol = GridView2ModelPos(xColumns, nViewCol);
+ Reference< XPropertySet> xCurrentCol;
+ if(xColumns.is())
+ xColumns->getByIndex(nModelCol) >>= xCurrentCol;
+ if (xCurrentCol.is())
+ strActiveField = ::comphelper::getString(xCurrentCol->getPropertyValue(FM_PROP_LABEL)).getStr();
+
+ // the text fo the current column
+ Reference< XIndexAccess> xColControls(xGridPeer, UNO_QUERY);
+ Reference< XInterface> xCurControl;
+ xColControls->getByIndex(nViewCol) >>= xCurControl;
+ ::rtl::OUString sInitialText;
+ if (IsSearchableControl(xCurControl, &sInitialText))
+ strInitialText = sInitialText.getStr();
+ }
+ }
+ }
+
+ // um eventuelle GridControls, die ich kenne, kuemmern
+ LoopGrids(GA_DISABLE_SYNC /*| GA_ENABLE_ROCTRLR*/);
+
+ // jetzt bin ich reif fuer den Dialog
+ // wenn die potentiellen Deadlocks, die durch die Benutzung des Solar-Mutex in MTs VCLX...-Klasen entstehen, irgendwann mal
+ // ausgeraeumt sind, sollte hier ein SM_USETHREAD rein, denn die Suche in einem eigenen Thread ist doch etwas fluessiger
+ // sollte allerdings irgendwie von dem unterliegenden Cursor abhaengig gemacht werden, DAO zum Beispiel ist nicht thread-sicher
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ AbstractFmSearchDialog* pDialog = NULL;
+ if ( pFact )
+ pDialog = pFact->CreateFmSearchDialog( &m_pShell->GetViewShell()->GetViewFrame()->GetWindow(), strInitialText, aContextNames, nInitialContext, LINK( this, FmXFormShell, OnSearchContextRequest ) );
+ DBG_ASSERT( pDialog, "FmXFormShell::ExecuteSearch: could not create the search dialog!" );
+ if ( pDialog )
+ {
+ pDialog->SetActiveField( strActiveField );
+ pDialog->SetFoundHandler( LINK( this, FmXFormShell, OnFoundData ) );
+ pDialog->SetCanceledNotFoundHdl( LINK( this, FmXFormShell, OnCanceledNotFound ) );
+ pDialog->Execute();
+ delete pDialog;
+ }
+
+ // GridControls wieder restaurieren
+ LoopGrids(GA_ENABLE_SYNC | GA_DISABLE_ROCTRLR);
+
+ m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
+ // da ich in OnFoundData (fals ich dort war) Controls markiert habe
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmXFormShell::GetY2KState(sal_uInt16& n)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::GetY2KState" );
+ if ( impl_checkDisposed() )
+ return sal_False;
+
+ if (m_pShell->IsDesignMode())
+ // im Design-Modus (ohne aktive Controls) soll sich das Haupt-Dokument darum kuemmern
+ return sal_False;
+
+ Reference< XForm> xForm( getActiveForm());
+ if (!xForm.is())
+ // kein aktuelles Formular (also insbesondere kein aktuelles Control) -> das Haupt-Dokument soll sich kuemmern
+ return sal_False;
+
+ Reference< XRowSet> xDB(xForm, UNO_QUERY);
+ DBG_ASSERT(xDB.is(), "FmXFormShell::GetY2KState : current form has no dbform-interface !");
+
+ Reference< XNumberFormatsSupplier> xSupplier( getNumberFormats(OStaticDataAccessTools().getRowSetConnection(xDB), sal_False));
+ if (xSupplier.is())
+ {
+ Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
+ if (xSet.is())
+ {
+ try
+ {
+ Any aVal( xSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TwoDigitDateStart"))) );
+ aVal >>= n;
+ return sal_True;
+ }
+ catch(Exception&)
+ {
+ }
+
+ }
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::SetY2KState(sal_uInt16 n)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetY2KState" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XForm > xActiveForm( getActiveForm());
+ Reference< XRowSet > xActiveRowSet( xActiveForm, UNO_QUERY );
+ if ( xActiveRowSet.is() )
+ {
+ Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getRowSetConnection( xActiveRowSet ), sal_False ) );
+ if (xSupplier.is())
+ {
+ Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
+ if (xSet.is())
+ {
+ try
+ {
+ Any aVal;
+ aVal <<= n;
+ xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TwoDigitDateStart")), aVal);
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmXFormShell::SetY2KState: Exception occurred!");
+ }
+
+ }
+ return;
+ }
+ }
+
+ // kein aktives Formular gefunden -> alle aktuell vorhandenen Formulare durchiterieren
+ Reference< XIndexAccess> xCurrentForms( m_xForms);
+ if (!xCurrentForms.is())
+ { // im alive-Modus sind meine Forms nicht gesetzt, wohl aber die an der Page
+ if (m_pShell->GetCurPage())
+ xCurrentForms = Reference< XIndexAccess>( m_pShell->GetCurPage()->GetForms( false ), UNO_QUERY );
+ }
+ if (!xCurrentForms.is())
+ return;
+
+ ::comphelper::IndexAccessIterator aIter(xCurrentForms);
+ Reference< XInterface> xCurrentElement( aIter.Next());
+ while (xCurrentElement.is())
+ {
+ // ist das aktuelle Element eine DatabaseForm ?
+ Reference< XRowSet> xElementAsRowSet( xCurrentElement, UNO_QUERY );
+ if ( xElementAsRowSet.is() )
+ {
+ Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getRowSetConnection( xElementAsRowSet ), sal_False ) );
+ if (!xSupplier.is())
+ continue;
+
+ Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings());
+ if (xSet.is())
+ {
+ try
+ {
+ Any aVal;
+ aVal <<= n;
+ xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TwoDigitDateStart")), aVal);
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmXFormShell::SetY2KState: Exception occurred!");
+ }
+
+ }
+ }
+ xCurrentElement = aIter.Next();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::CloseExternalFormViewer()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::CloseExternalFormViewer" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if (!m_xExternalViewController.is())
+ return;
+
+ Reference< ::com::sun::star::frame::XFrame> xExternalViewFrame( m_xExternalViewController->getFrame());
+ Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
+ if (!xCommLink.is())
+ return;
+
+ xExternalViewFrame->setComponent(NULL,NULL);
+ ::comphelper::disposeComponent(xExternalViewFrame);
+ m_xExternalViewController = NULL;
+ m_xExtViewTriggerController = NULL;
+ m_xExternalDisplayedForm = NULL;
+}
+
+//------------------------------------------------------------------------------
+Reference< XResultSet> FmXFormShell::getInternalForm(const Reference< XResultSet>& _xForm) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getInternalForm" );
+ if ( impl_checkDisposed() )
+ return NULL;
+
+ Reference< runtime::XFormController> xExternalCtrlr(m_xExternalViewController, UNO_QUERY);
+ if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel()))
+ {
+ DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !");
+ return m_xExternalDisplayedForm;
+ }
+ return _xForm;
+}
+
+//------------------------------------------------------------------------------
+Reference< XForm> FmXFormShell::getInternalForm(const Reference< XForm>& _xForm) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getInternalForm" );
+ if ( impl_checkDisposed() )
+ return NULL;
+
+ Reference< runtime::XFormController > xExternalCtrlr(m_xExternalViewController, UNO_QUERY);
+ if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel()))
+ {
+ DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !");
+ return Reference< XForm>(m_xExternalDisplayedForm, UNO_QUERY);
+ }
+ return _xForm;
+}
+
+//------------------------------------------------------------------------
+namespace
+{
+ static bool lcl_isNavigationRelevant( sal_Int32 _nWhich )
+ {
+ return ( _nWhich == SID_FM_RECORD_FIRST )
+ || ( _nWhich == SID_FM_RECORD_PREV )
+ || ( _nWhich == SID_FM_RECORD_NEXT )
+ || ( _nWhich == SID_FM_RECORD_LAST )
+ || ( _nWhich == SID_FM_RECORD_NEW );
+ }
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::IsFormSlotEnabled( sal_Int32 _nSlot, FeatureState* _pCompleteState )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::IsFormSlotEnabled" );
+ const ::svx::ControllerFeatures& rController =
+ lcl_isNavigationRelevant( _nSlot )
+ ? getNavControllerFeatures()
+ : getActiveControllerFeatures();
+
+ if ( !_pCompleteState )
+ return rController->isEnabled( _nSlot );
+
+ rController->getState( _nSlot, *_pCompleteState );
+ return _pCompleteState->Enabled;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::ExecuteFormSlot( sal_Int32 _nSlot )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ExecuteFormSlot" );
+ const ::svx::ControllerFeatures& rController =
+ lcl_isNavigationRelevant( _nSlot )
+ ? getNavControllerFeatures()
+ : getActiveControllerFeatures();
+
+ rController->execute( _nSlot );
+
+ if ( _nSlot == SID_FM_RECORD_UNDO )
+ {
+ // if we're doing an UNDO, *and* if the affected form is the form which we also display
+ // as external view, then we need to reset the controls of the external form, too
+ if ( getInternalForm( getActiveForm() ) == m_xExternalDisplayedForm )
+ {
+ Reference< XIndexAccess > xContainer( m_xExternalDisplayedForm, UNO_QUERY );
+ if ( xContainer.is() )
+ {
+ Reference< XReset > xReset;
+ for ( sal_Int32 i = 0; i < xContainer->getCount(); ++i )
+ {
+ if ( ( xContainer->getByIndex( i ) >>= xReset ) && xReset.is() )
+ {
+ // no resets on sub forms
+ Reference< XForm > xAsForm( xReset, UNO_QUERY );
+ if ( !xAsForm.is() )
+ xReset->reset();
+ }
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::impl_switchActiveControllerListening( const bool _bListen )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::impl_switchActiveControllerListening" );
+ Reference< XComponent> xComp( m_xActiveController, UNO_QUERY );
+ if ( !xComp.is() )
+ return;
+
+ if ( _bListen )
+ xComp->addEventListener( (XFormControllerListener*)this );
+ else
+ xComp->removeEventListener( (XFormControllerListener*)this );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::setActiveController( const Reference< runtime::XFormController >& xController, sal_Bool _bNoSaveOldContent )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::setActiveController" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if (m_bChangingDesignMode)
+ return;
+ DBG_ASSERT(!m_pShell->IsDesignMode(), "nur im alive mode verwenden");
+
+ // Ist die Routine ein zweites Mal gerufen worden,
+ // dann sollte der Focus nicht mehr umgesetzt werden
+ if (m_bInActivate)
+ {
+ m_bSetFocus = xController != m_xActiveController;
+ return;
+ }
+
+ if (xController != m_xActiveController)
+ {
+ ::osl::ClearableMutexGuard aGuard(m_aAsyncSafety);
+ // switch all nav dispatchers belonging to the form of the current nav controller to 'non active'
+ Reference< XResultSet> xNavigationForm;
+ if (m_xNavigationController.is())
+ xNavigationForm = Reference< XResultSet>(m_xNavigationController->getModel(), UNO_QUERY);
+ aGuard.clear();
+
+ m_bInActivate = sal_True;
+
+ // check if the 2 controllers serve different forms
+ Reference< XResultSet> xOldForm;
+ if (m_xActiveController.is())
+ xOldForm = Reference< XResultSet>(m_xActiveController->getModel(), UNO_QUERY);
+ Reference< XResultSet> xNewForm;
+ if (xController.is())
+ xNewForm = Reference< XResultSet>(xController->getModel(), UNO_QUERY);
+ xOldForm = getInternalForm(xOldForm);
+ xNewForm = getInternalForm(xNewForm);
+
+ sal_Bool bDifferentForm = ( xOldForm.get() != xNewForm.get() );
+ sal_Bool bNeedSave = bDifferentForm && !_bNoSaveOldContent;
+ // we save the content of the old form if we move to a new form, and saving old content is allowed
+
+ if ( m_xActiveController.is() && bNeedSave )
+ {
+ // beim Wechsel des Controllers den Inhalt speichern, ein Commit
+ // wurde bereits ausgefuehrt
+ if ( m_aActiveControllerFeatures->commitCurrentControl() )
+ {
+ m_bSetFocus = sal_True;
+ if ( m_aActiveControllerFeatures->isModifiedRow() )
+ {
+ sal_Bool bIsNew = m_aActiveControllerFeatures->isInsertionRow();
+ sal_Bool bResult = m_aActiveControllerFeatures->commitCurrentRecord();
+ if ( !bResult && m_bSetFocus )
+ {
+ // if we couldn't save the current record, set the focus back to the
+ // current control
+ Reference< XWindow > xWindow( m_xActiveController->getCurrentControl(), UNO_QUERY );
+ if ( xWindow.is() )
+ xWindow->setFocus();
+ m_bInActivate = sal_False;
+ return;
+ }
+ else if ( bResult && bIsNew )
+ {
+ Reference< XResultSet > xCursor( m_aActiveControllerFeatures->getCursor().get() );
+ if ( xCursor.is() )
+ {
+ DO_SAFE( xCursor->last(); );
+ }
+ }
+ }
+ }
+ }
+
+ stopListening();
+
+ impl_switchActiveControllerListening( false );
+
+ m_aActiveControllerFeatures.dispose();
+ m_xActiveController = xController;
+ if ( m_xActiveController.is() )
+ m_aActiveControllerFeatures.assign( m_xActiveController );
+
+ impl_switchActiveControllerListening( true );
+
+ if ( m_xActiveController.is() )
+ m_xActiveForm = getInternalForm( Reference< XForm >( m_xActiveController->getModel(), UNO_QUERY ) );
+ else
+ m_xActiveForm = NULL;
+
+ startListening();
+
+ // activate all dispatchers belonging to form of the new navigation controller
+ xNavigationForm = NULL;
+ if (m_xNavigationController.is())
+ xNavigationForm = Reference< XResultSet>(m_xNavigationController->getModel(), UNO_QUERY);
+
+ m_bInActivate = sal_False;
+
+ m_pShell->UIFeatureChanged();
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
+
+ InvalidateSlot(SID_FM_FILTER_NAVIGATOR_CONTROL, sal_True);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::getCurrentSelection( InterfaceBag& /* [out] */ _rSelection ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::getCurrentSelection" );
+ _rSelection = m_aCurrentSelection;
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::setCurrentSelectionFromMark( const SdrMarkList& _rMarkList )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::setCurrentSelectionFromMark" );
+ m_aLastKnownMarkedControls.clear();
+
+ if ( ( _rMarkList.GetMarkCount() > 0 ) && isControlList( _rMarkList ) )
+ collectInterfacesFromMarkList( _rMarkList, m_aLastKnownMarkedControls );
+
+ return setCurrentSelection( m_aLastKnownMarkedControls );
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::selectLastMarkedControls()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::selectLastMarkedControls" );
+ return setCurrentSelection( m_aLastKnownMarkedControls );
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::setCurrentSelection( const InterfaceBag& _rSelection )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::setCurrentSelection" );
+ if ( impl_checkDisposed() )
+ return false;
+
+ DBG_ASSERT( m_pShell->IsDesignMode(), "FmXFormShell::setCurrentSelection: only to be used in design mode!" );
+
+ if ( _rSelection.empty() && m_aCurrentSelection.empty() )
+ // nothing to do
+ return false;
+
+ if ( _rSelection.size() == m_aCurrentSelection.size() )
+ {
+ InterfaceBag::const_iterator aNew = _rSelection.begin();
+ InterfaceBag::const_iterator aOld = m_aCurrentSelection.begin();
+ for ( ; aNew != _rSelection.end(); ++aNew, ++aOld )
+ {
+ OSL_ENSURE( Reference< XInterface >( *aNew, UNO_QUERY ).get() == aNew->get(), "FmXFormShell::setCurrentSelection: new interface not normalized!" );
+ OSL_ENSURE( Reference< XInterface >( *aOld, UNO_QUERY ).get() == aOld->get(), "FmXFormShell::setCurrentSelection: old interface not normalized!" );
+
+ if ( aNew->get() != aOld->get() )
+ break;
+ }
+
+ if ( aNew == _rSelection.end() )
+ // both bags equal
+ return false;
+ }
+
+ // the following is some strange code to ensure that when you have two grid controls in a document,
+ // only one of them can have a selected column.
+ // TODO: this should happen elsewhere, but not here - shouldn't it?
+ if ( !m_aCurrentSelection.empty() )
+ {
+ Reference< XChild > xCur; if ( m_aCurrentSelection.size() == 1 ) xCur = xCur.query( *m_aCurrentSelection.begin() );
+ Reference< XChild > xNew; if ( _rSelection.size() == 1 ) xNew = xNew.query( *_rSelection.begin() );
+
+ // is there nothing to be selected, or the parents differ, and the parent of the current object
+ // is a selection supplier, then deselect
+ if ( xCur.is() && ( !xNew.is() || ( xCur->getParent() != xNew->getParent() ) ) )
+ {
+ Reference< XSelectionSupplier > xSel( xCur->getParent(), UNO_QUERY );
+ if ( xSel.is() )
+ xSel->select( Any() );
+ }
+ }
+
+ m_aCurrentSelection = _rSelection;
+
+ // determine the form which all the selected obj�cts belong to, if any
+ Reference< XForm > xNewCurrentForm;
+ for ( InterfaceBag::const_iterator loop = m_aCurrentSelection.begin();
+ loop != m_aCurrentSelection.end();
+ ++loop
+ )
+ {
+ Reference< XForm > xThisRoundsForm( GetForm( *loop ) );
+ OSL_ENSURE( xThisRoundsForm.is(), "FmXFormShell::setCurrentSelection: *everything* should belong to a form!" );
+
+ if ( !xNewCurrentForm.is() )
+ { // the first form we encounterd
+ xNewCurrentForm = xThisRoundsForm;
+ }
+ else if ( xNewCurrentForm != xThisRoundsForm )
+ { // different forms -> no "current form" at all
+ xNewCurrentForm.clear();
+ break;
+ }
+ }
+
+ if ( !m_aCurrentSelection.empty() )
+ impl_updateCurrentForm( xNewCurrentForm );
+
+ // ensure some slots are updated
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( SelObjectSlotMap ); ++i )
+ InvalidateSlot( SelObjectSlotMap[i], sal_False);
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::isSolelySelected( const Reference< XInterface >& _rxObject )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::isSolelySelected" );
+ return ( m_aCurrentSelection.size() == 1 ) && ( *m_aCurrentSelection.begin() == _rxObject );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::forgetCurrentForm()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::forgetCurrentForm" );
+ if ( !m_xCurrentForm.is() )
+ return;
+
+ // reset ...
+ impl_updateCurrentForm( NULL );
+
+ // ... and try finding a new current form
+ // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
+ impl_defaultCurrentForm_nothrow();
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::impl_updateCurrentForm( const Reference< XForm >& _rxNewCurForm )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::impl_updateCurrentForm" );
+ if ( impl_checkDisposed() )
+ return;
+
+ m_xCurrentForm = _rxNewCurForm;
+
+ // propagate to the FormPage(Impl)
+ FmFormPage* pPage = m_pShell->GetCurPage();
+ if ( pPage )
+ pPage->GetImpl().setCurForm( m_xCurrentForm );
+
+ // ensure the UI which depends on the current form is up-to-date
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( DlgSlotMap ); ++i )
+ InvalidateSlot( DlgSlotMap[i], sal_False );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::startListening()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::startListening" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY);
+ if (xDatabaseForm.is() && getRowSetConnection(xDatabaseForm).is())
+ {
+ Reference< XPropertySet> xActiveFormSet(m_xActiveForm, UNO_QUERY);
+ if (xActiveFormSet.is())
+ {
+ // wenn es eine Datenquelle gibt, dann den Listener aufbauen
+ // TODO: this is strange - shouldn't this depend on a isLoaded instead of
+ // a "has command value"? Finally, the command value only means that it was
+ // intended to be loaded, not that it actually *is* loaded
+ ::rtl::OUString aSource = ::comphelper::getString(xActiveFormSet->getPropertyValue(FM_PROP_COMMAND));
+ if (aSource.getLength())
+ {
+ m_bDatabaseBar = sal_True;
+
+ xActiveFormSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate;
+
+ switch (m_eNavigate)
+ {
+ case NavigationBarMode_PARENT:
+ {
+ // suchen des Controllers, ueber den eine Navigation moeglich ist
+ Reference< XChild> xChild(m_xActiveController, UNO_QUERY);
+ Reference< runtime::XFormController > xParent;
+ while (xChild.is())
+ {
+ xChild = Reference< XChild>(xChild->getParent(), UNO_QUERY);
+ xParent = Reference< runtime::XFormController >(xChild, UNO_QUERY);
+ Reference< XPropertySet> xParentSet;
+ if (xParent.is())
+ xParentSet = Reference< XPropertySet>(xParent->getModel(), UNO_QUERY);
+ if (xParentSet.is())
+ {
+ xParentSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate;
+ if (m_eNavigate == NavigationBarMode_CURRENT)
+ break;
+ }
+ }
+ m_xNavigationController = xParent;
+ }
+ break;
+
+ case NavigationBarMode_CURRENT:
+ m_xNavigationController = m_xActiveController;
+ break;
+
+ default:
+ m_xNavigationController = NULL;
+ m_bDatabaseBar = sal_False;
+ }
+
+ m_aNavControllerFeatures.dispose();
+ if ( m_xNavigationController.is() && ( m_xNavigationController != m_xActiveController ) )
+ m_aNavControllerFeatures.assign( m_xNavigationController );
+
+ // an dem Controller, der die Navigation regelt, wg. RecordCount lauschen
+ Reference< XPropertySet> xNavigationSet;
+ if (m_xNavigationController.is())
+ {
+ xNavigationSet = Reference< XPropertySet>(m_xNavigationController->getModel(), UNO_QUERY);
+ if (xNavigationSet.is())
+ xNavigationSet->addPropertyChangeListener(FM_PROP_ROWCOUNT,this);
+ }
+ return;
+ }
+ }
+ }
+
+ m_eNavigate = NavigationBarMode_NONE;
+ m_bDatabaseBar = sal_False;
+ m_xNavigationController = NULL;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::stopListening()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::stopListening" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY);
+ if ( xDatabaseForm.is() )
+ {
+ if (m_xNavigationController.is())
+ {
+ Reference< XPropertySet> xSet(m_xNavigationController->getModel(), UNO_QUERY);
+ if (xSet.is())
+ xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this);
+
+ }
+ }
+
+ m_bDatabaseBar = sal_False;
+ m_eNavigate = NavigationBarMode_NONE;
+ m_xNavigationController = NULL;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::ShowSelectionProperties( sal_Bool bShow )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ShowSelectionProperties" );
+ if ( impl_checkDisposed() )
+ return;
+
+ // if the window is already visible, only update the state
+ sal_Bool bHasChild = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_PROPERTIES );
+ if ( bHasChild && bShow )
+ UpdateSlot( SID_FM_PROPERTY_CONTROL );
+
+ // else toggle state
+ else
+ m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES);
+
+ InvalidateSlot( SID_FM_PROPERTIES, sal_False );
+ InvalidateSlot( SID_FM_CTL_PROPERTIES, sal_False );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormShell, OnFoundData, FmFoundRecordInformation*, pfriWhere)
+{
+ if ( impl_checkDisposed() )
+ return 0;
+
+ DBG_ASSERT((pfriWhere->nContext >= 0) && (pfriWhere->nContext < (sal_Int16)m_aSearchForms.size()),
+ "FmXFormShell::OnFoundData : ungueltiger Kontext !");
+ Reference< XForm> xForm( m_aSearchForms.at(pfriWhere->nContext));
+ DBG_ASSERT(xForm.is(), "FmXFormShell::OnFoundData : ungueltige Form !");
+
+ Reference< XRowLocate> xCursor(xForm, UNO_QUERY);
+ if (!xCursor.is())
+ return 0; // was soll ich da machen ?
+
+ // zum Datensatz
+ try
+ {
+ xCursor->moveToBookmark(pfriWhere->aPosition);
+ }
+ catch(const SQLException&)
+ {
+ OSL_ENSURE(0,"Can position on bookmark!");
+ }
+
+ LoopGrids(GA_FORCE_SYNC);
+
+ // und zum Feld (dazu habe ich vor dem Start des Suchens die XVclComponent-Interfaces eingesammelt)
+ DBG_ASSERT(pfriWhere->nFieldPos < m_arrSearchedControls.Count(), "FmXFormShell::OnFoundData : ungueltige Daten uebergeben !");
+ SdrObject* pObject = m_arrSearchedControls.GetObject(pfriWhere->nFieldPos);
+ DBG_ASSERT(pObject != NULL, "FmXFormShell::OnFoundData : unerwartet : ungueltiges VclControl-Interface");
+
+ m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
+ m_pShell->GetFormView()->MarkObj(pObject, m_pShell->GetFormView()->GetSdrPageView());
+
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
+ Reference< XControlModel > xControlModel( pFormObject ? pFormObject->GetUnoControlModel() : Reference< XControlModel >() );
+ DBG_ASSERT( xControlModel.is(), "FmXFormShell::OnFoundData: invalid control!" );
+ if ( !xControlModel.is() )
+ return 0;
+
+ // disable the permanent cursor for the last grid we found a record
+ if (m_xLastGridFound.is() && (m_xLastGridFound != xControlModel))
+ {
+ Reference< XPropertySet> xOldSet(m_xLastGridFound, UNO_QUERY);
+ xOldSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, makeAny( (sal_Bool)sal_False ) );
+ Reference< XPropertyState> xOldSetState(xOldSet, UNO_QUERY);
+ if (xOldSetState.is())
+ xOldSetState->setPropertyToDefault(FM_PROP_CURSORCOLOR);
+ else
+ xOldSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any());
+ }
+
+ // wenn das Feld sich in einem GridControl befindet, muss ich dort noch in die entsprechende Spalte gehen
+ sal_Int32 nGridColumn = m_arrRelativeGridColumn.GetObject(pfriWhere->nFieldPos);
+ if (nGridColumn != -1)
+ { // dummer weise muss ich mir das Control erst wieder besorgen
+ Reference< XControl> xControl( impl_getControl( xControlModel, *pFormObject ) );
+ Reference< XGrid> xGrid(xControl, UNO_QUERY);
+ DBG_ASSERT(xGrid.is(), "FmXFormShell::OnFoundData : ungueltiges Control !");
+ // wenn eine der Asserts anschlaegt, habe ich beim Aufbauen von m_arrSearchedControls wohl was falsch gemacht
+
+ // enable a permanent cursor for the grid so we can see the found text
+ Reference< XPropertySet> xModelSet(xControlModel, UNO_QUERY);
+ DBG_ASSERT(xModelSet.is(), "FmXFormShell::OnFoundData : invalid control model (no property set) !");
+ xModelSet->setPropertyValue( FM_PROP_ALWAYSSHOWCURSOR, makeAny( (sal_Bool)sal_True ) );
+ xModelSet->setPropertyValue( FM_PROP_CURSORCOLOR, makeAny( sal_Int32( COL_LIGHTRED ) ) );
+ m_xLastGridFound = xControlModel;
+
+ if ( xGrid.is() )
+ xGrid->setCurrentColumnPosition((sal_Int16)nGridColumn);
+ }
+
+ // als der Cursor neu positioniert wurde, habe ich (in positioned) meine Formularleisten-Slots invalidiert, aber das greift
+ // hier dummerweise nicht, da i.A. ja der (modale) Suchdialog oben ist ... also Gewalt ...
+ sal_uInt16 nPos = 0;
+ while (DatabaseSlotMap[nPos])
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(DatabaseSlotMap[nPos++]);
+ // leider geht das Update im Gegensatz zum Invalidate nur mit einzelnen Slots)
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormShell, OnCanceledNotFound, FmFoundRecordInformation*, pfriWhere)
+{
+ if ( impl_checkDisposed() )
+ return 0;
+
+ DBG_ASSERT((pfriWhere->nContext >= 0) && (pfriWhere->nContext < (sal_Int16)m_aSearchForms.size()),
+ "FmXFormShell::OnCanceledNotFound : ungueltiger Kontext !");
+ Reference< XForm> xForm( m_aSearchForms.at(pfriWhere->nContext));
+ DBG_ASSERT(xForm.is(), "FmXFormShell::OnCanceledNotFound : ungueltige Form !");
+
+ Reference< XRowLocate> xCursor(xForm, UNO_QUERY);
+ if (!xCursor.is())
+ return 0; // was soll ich da machen ?
+
+ // zum Datensatz
+ try
+ {
+ xCursor->moveToBookmark(pfriWhere->aPosition);
+ }
+ catch(const SQLException&)
+ {
+ OSL_ENSURE(0,"Can position on bookmark!");
+ }
+
+
+ m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView());
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormShell, OnSearchContextRequest, FmSearchContext*, pfmscContextInfo)
+{
+ if ( impl_checkDisposed() )
+ return 0;
+
+ DBG_ASSERT(pfmscContextInfo->nContext < (sal_Int16)m_aSearchForms.size(), "FmXFormShell::OnSearchContextRequest : invalid parameter !");
+ Reference< XForm> xForm( m_aSearchForms.at(pfmscContextInfo->nContext));
+ DBG_ASSERT(xForm.is(), "FmXFormShell::OnSearchContextRequest : unexpected : invalid context !");
+
+ Reference< XResultSet> xIter(xForm, UNO_QUERY);
+ DBG_ASSERT(xIter.is(), "FmXFormShell::OnSearchContextRequest : unexpected : context has no iterator !");
+
+ // --------------------------------------------------------------------------------------------
+ // die Liste der zu involvierenden Felder zusammenstellen (sind die ControlSources aller Felder, die eine solche Eigenschaft habe)
+ UniString strFieldList, sFieldDisplayNames;
+ m_arrSearchedControls.Remove(0, m_arrSearchedControls.Count());
+ m_arrRelativeGridColumn.Remove(0, m_arrRelativeGridColumn.Count());
+
+ // folgendes kleines Problem : Ich brauche, um gefundene Felder zu markieren, SdrObjekte. Um hier festzustellen, welche Controls
+ // ich in die Suche einbeziehen soll, brauche ich Controls (also XControl-Interfaces). Ich muss also ueber eines von beiden
+ // iterieren und mir das jeweils andere besorgen. Dummerweise gibt es keine direkte Verbindung zwischen beiden Welten (abgesehen
+ // von einem GetUnoControl an SdrUnoObject, das aber ein OutputDevice verlangt, womit ich nichts anfangen kann).
+ // Allerdings komme ich sowohl von einem Control als auch von einem SdrObject zum Model, und damit ist mir mit einer doppelten
+ // Schleife die Zuordnung SdrObject<->Control moeglich.
+ // Die Alternative zu dieser (unschoenen und sicher auch nicht ganz fixen) Loesung waere, auf das Cachen der SdrObjects zu
+ // verzichten, was dann aber in OnFoundData zu wesentlicher Mehrarbeit fuehren wuerde (da ich mir dort jedesmal das SdrObject
+ // erst besorgen muesste). Da aber OnFoundData i.d.R. oefter aufgerufen wird als ExecuteSearch, erledige ich das hier.
+
+ Reference< XNameAccess> xValidFormFields;
+ Reference< XColumnsSupplier> xSupplyCols(xIter, UNO_QUERY);
+ DBG_ASSERT(xSupplyCols.is(), "FmXFormShell::OnSearchContextRequest : invalid cursor : no columns supplier !");
+ if (xSupplyCols.is())
+ xValidFormFields = xSupplyCols->getColumns();
+ DBG_ASSERT(xValidFormFields.is(), "FmXFormShell::OnSearchContextRequest : form has no fields !");
+
+ // aktuelle(r) Page/Controller
+ FmFormPage* pCurrentPage = m_pShell->GetCurPage();
+ DBG_ASSERT(pCurrentPage!=NULL, "FmXFormShell::OnSearchContextRequest : no page !");
+ // alle Sdr-Controls dieser Seite durchsuchen ...
+ ::rtl::OUString sControlSource, aName;
+
+ SdrObjListIter aPageIter( *pCurrentPage );
+ while ( aPageIter.IsMore() )
+ {
+ SdrObject* pCurrent = aPageIter.Next();
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pCurrent );
+ // note that in case pCurrent is a virtual object, pFormObject points to the referenced object
+
+ if ( !pFormObject )
+ continue;
+
+ // the current object's model, in different tastes
+ Reference< XControlModel> xControlModel( pFormObject->GetUnoControlModel() );
+ Reference< XFormComponent > xCurrentFormComponent( xControlModel, UNO_QUERY );
+ DBG_ASSERT( xCurrentFormComponent.is(), "FmXFormShell::OnSearchContextRequest: invalid objects!" );
+ if ( !xCurrentFormComponent.is() )
+ continue;
+
+ // does the component belong to the form which we're interested in?
+ if ( xCurrentFormComponent->getParent() != xForm )
+ continue;
+
+ // ... nach der ControlSource-Eigenschaft fragen
+ SearchableControlIterator iter( xCurrentFormComponent );
+ Reference< XControl> xControl;
+ // das Control, das als Model xControlModel hat
+ // (das folgende while kann mehrmals durchlaufen werden, ohne dass das Control sich aendert, dann muss
+ // ich nicht jedesmal neu suchen)
+
+ Reference< XInterface > xSearchable( iter.Next() );
+ while ( xSearchable.is() )
+ {
+ sControlSource = iter.getCurrentValue();
+ if ( sControlSource.getLength() == 0 )
+ { // das aktuelle Element hat keine ControlSource, also ist es ein GridControl (das ist das einzige, was
+ // der SearchableControlIterator noch zulaesst)
+ xControl = impl_getControl( xControlModel, *pFormObject );
+ DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
+
+ Reference< XGridPeer> xGridPeer;
+ if ( xControl.is() )
+ xGridPeer.set( xControl->getPeer(), UNO_QUERY );
+ do
+ {
+ if (!xGridPeer.is())
+ break;
+
+ Reference< XIndexAccess> xPeerContainer(xGridPeer, UNO_QUERY);
+ if (!xPeerContainer.is())
+ break;
+
+ Reference< XIndexAccess> xModelColumns(xGridPeer->getColumns(), UNO_QUERY);
+ DBG_ASSERT(xModelColumns.is(), "FmXFormShell::OnSearchContextRequest : there is a grid control without columns !");
+ // the case 'no columns' should be indicated with an empty container, I think ...
+ DBG_ASSERT(xModelColumns->getCount() >= xPeerContainer->getCount(), "FmXFormShell::OnSearchContextRequest : impossible : have more view than model columns !");
+
+ Reference< XInterface> xCurrentColumn;
+ for (sal_Int16 nViewPos=0; nViewPos<xPeerContainer->getCount(); ++nViewPos)
+ {
+ xPeerContainer->getByIndex(nViewPos) >>= xCurrentColumn;
+ if (!xCurrentColumn.is())
+ continue;
+
+ // can we use this column control fo searching ?
+ if (!IsSearchableControl(xCurrentColumn))
+ continue;
+
+ sal_Int16 nModelPos = GridView2ModelPos(xModelColumns, nViewPos);
+ Reference< XPropertySet> xCurrentColModel;
+ xModelColumns->getByIndex(nModelPos) >>= xCurrentColModel;
+ aName = ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_CONTROLSOURCE));
+ // the cursor has a field matching the control source ?
+ if (xValidFormFields->hasByName(aName))
+ {
+ strFieldList += aName.getStr();
+ strFieldList += ';';
+
+ sFieldDisplayNames += ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_LABEL)).getStr();
+ sFieldDisplayNames += ';';
+
+ pfmscContextInfo->arrFields.push_back(xCurrentColumn);
+
+ // und das SdrObjekt zum Feld
+ m_arrSearchedControls.C40_INSERT(SdrObject, pCurrent, m_arrSearchedControls.Count());
+ // die Nummer der Spalte
+ m_arrRelativeGridColumn.Insert(nViewPos, m_arrRelativeGridColumn.Count());
+ }
+ }
+ } while (sal_False);
+ }
+ else
+ {
+ if (sControlSource.getLength() && xValidFormFields->hasByName(sControlSource))
+ {
+ // jetzt brauche ich das Control zum SdrObject
+ if (!xControl.is())
+ {
+ xControl = impl_getControl( xControlModel, *pFormObject );
+ DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
+ }
+
+ if (IsSearchableControl(xControl))
+ { // alle Tests ueberstanden -> in die Liste mit aufnehmen
+ strFieldList += sControlSource.getStr();
+ strFieldList += ';';
+
+ // the label which should appear for the control :
+ sFieldDisplayNames += getLabelName(Reference< XPropertySet>(xControlModel, UNO_QUERY)).getStr();
+ sFieldDisplayNames += ';';
+
+ // das SdrObjekt merken (beschleunigt die Behandlung in OnFoundData)
+ m_arrSearchedControls.C40_INSERT(SdrObject, pCurrent, m_arrSearchedControls.Count());
+
+ // die Nummer der Spalte (hier ein Dummy, nur fuer GridControls interesant)
+ m_arrRelativeGridColumn.Insert(-1, m_arrRelativeGridColumn.Count());
+
+ // und fuer die formatierte Suche ...
+ pfmscContextInfo->arrFields.push_back(Reference< XInterface>(xControl, UNO_QUERY));
+ }
+ }
+ }
+
+ xSearchable = iter.Next();
+ }
+ }
+
+ strFieldList.EraseTrailingChars(';');
+ sFieldDisplayNames.EraseTrailingChars(';');
+
+ if (!pfmscContextInfo->arrFields.size())
+ {
+ pfmscContextInfo->arrFields.clear();
+ pfmscContextInfo->xCursor = NULL;
+ pfmscContextInfo->strUsedFields.Erase();
+ return 0L;
+ }
+
+ pfmscContextInfo->xCursor = xIter;
+ pfmscContextInfo->strUsedFields = strFieldList;
+ pfmscContextInfo->sFieldDisplayNames = sFieldDisplayNames;
+
+ // 66463 - 31.05.99 - FS
+ // wenn der Cursor sich in einem anderen RecordMode als STANDARD befindet, ruecksetzen
+ Reference< XPropertySet> xCursorSet(pfmscContextInfo->xCursor, UNO_QUERY);
+ Reference< XResultSetUpdate> xUpdateCursor(pfmscContextInfo->xCursor, UNO_QUERY);
+ if (xUpdateCursor.is() && xCursorSet.is() && xCursorSet.is())
+ {
+ if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISNEW)))
+ xUpdateCursor->moveToCurrentRow();
+ else if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISMODIFIED)))
+ xUpdateCursor->cancelRowUpdates();
+ }
+
+ return pfmscContextInfo->arrFields.size();
+}
+
+ // XContainerListener
+//------------------------------------------------------------------------------
+void FmXFormShell::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::elementInserted" );
+ if ( impl_checkDisposed() )
+ return;
+
+ // neues Object zum lauschen
+ Reference< XInterface> xTemp;
+ evt.Element >>= xTemp;
+ AddElement(xTemp);
+ m_pShell->DetermineForms(sal_True);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::elementReplaced" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XInterface> xTemp;
+ evt.ReplacedElement >>= xTemp;
+ RemoveElement(xTemp);
+ evt.Element >>= xTemp;
+ AddElement(xTemp);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::elementRemoved" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XInterface> xTemp;
+ evt.Element >>= xTemp;
+ RemoveElement(xTemp);
+ m_pShell->DetermineForms(sal_True);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::UpdateForms( sal_Bool _bInvalidate )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::UpdateForms" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XIndexAccess > xForms;
+
+ FmFormPage* pPage = m_pShell->GetCurPage();
+ if ( pPage )
+ {
+ if ( m_pShell->m_bDesignMode )
+ xForms = xForms.query( pPage->GetForms( false ) );
+ }
+
+ if ( m_xForms != xForms )
+ {
+ RemoveElement( m_xForms );
+ m_xForms = xForms;
+ AddElement( m_xForms );
+ }
+
+ m_pShell->DetermineForms( _bInvalidate );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::AddElement(const Reference< XInterface>& _xElement)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::AddElement" );
+ if ( impl_checkDisposed() )
+ return;
+ impl_AddElement_nothrow(_xElement);
+}
+// -----------------------------------------------------------------------------
+void FmXFormShell::impl_AddElement_nothrow(const Reference< XInterface>& Element)
+{
+ // am Container horchen
+ const Reference< XIndexContainer> xContainer(Element, UNO_QUERY);
+ if (xContainer.is())
+ {
+ const sal_uInt32 nCount = xContainer->getCount();
+ Reference< XInterface> xElement;
+ for (sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ xElement.set(xContainer->getByIndex(i),UNO_QUERY);
+ impl_AddElement_nothrow(xElement);
+ }
+
+ const Reference< XContainer> xCont(Element, UNO_QUERY);
+ if (xCont.is())
+ xCont->addContainerListener(this);
+ }
+
+ const Reference< ::com::sun::star::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY);
+ if (xSelSupplier.is())
+ xSelSupplier->addSelectionChangeListener(this);
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::RemoveElement(const Reference< XInterface>& Element)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::RemoveElement" );
+ if ( impl_checkDisposed() )
+ return;
+ impl_RemoveElement_nothrow(Element);
+}
+//------------------------------------------------------------------------------
+void FmXFormShell::impl_RemoveElement_nothrow(const Reference< XInterface>& Element)
+{
+ const Reference< ::com::sun::star::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY);
+ if (xSelSupplier.is())
+ xSelSupplier->removeSelectionChangeListener(this);
+
+ // Verbindung zu Kindern aufheben
+ const Reference< XIndexContainer> xContainer(Element, UNO_QUERY);
+ if (xContainer.is())
+ {
+ const Reference< XContainer> xCont(Element, UNO_QUERY);
+ if (xCont.is())
+ xCont->removeContainerListener(this);
+
+ const sal_uInt32 nCount = xContainer->getCount();
+ Reference< XInterface> xElement;
+ for (sal_uInt32 i = 0; i < nCount; i++)
+ {
+ xElement.set(xContainer->getByIndex(i),UNO_QUERY);
+ impl_RemoveElement_nothrow(xElement);
+ }
+ }
+
+ InterfaceBag::iterator wasSelectedPos = m_aCurrentSelection.find( Element );
+ if ( wasSelectedPos != m_aCurrentSelection.end() )
+ m_aCurrentSelection.erase( wasSelectedPos );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::selectionChanged(const EventObject& rEvent) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::selectionChanged" );
+ if ( impl_checkDisposed() )
+ return;
+
+ Reference< XSelectionSupplier > xSupplier( rEvent.Source, UNO_QUERY );
+ Reference< XInterface > xSelObj( xSupplier->getSelection(), UNO_QUERY );
+ // es wurde eine Selektion weggenommen, dieses kann nur durch die Shell vorgenommen werden
+ if ( !xSelObj.is() )
+ return;
+
+ EnableTrackProperties(sal_False);
+
+ sal_Bool bMarkChanged = m_pShell->GetFormView()->checkUnMarkAll(rEvent.Source);
+ Reference< XForm > xNewForm( GetForm( rEvent.Source ) );
+
+ InterfaceBag aNewSelection;
+ aNewSelection.insert( Reference< XInterface >( xSelObj, UNO_QUERY ) );
+
+ if ( setCurrentSelection( aNewSelection ) && IsPropBrwOpen() )
+ ShowSelectionProperties( sal_True );
+
+ EnableTrackProperties(sal_True);
+
+ if ( bMarkChanged )
+ m_pShell->NotifyMarkListChanged( m_pShell->GetFormView() );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormShell, OnTimeOut, void*, /*EMPTYTAG*/)
+{
+ if ( impl_checkDisposed() )
+ return 0;
+
+ if (m_pShell->IsDesignMode() && m_pShell->GetFormView())
+ SetSelection(m_pShell->GetFormView()->GetMarkedObjectList());
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::SetSelectionDelayed()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetSelectionDelayed" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if (m_pShell->IsDesignMode() && IsTrackPropertiesEnabled() && !m_aMarkTimer.IsActive())
+ m_aMarkTimer.Start();
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::SetSelection(const SdrMarkList& rMarkList)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetSelection" );
+ if ( impl_checkDisposed() )
+ return;
+
+ DetermineSelection(rMarkList);
+ m_pShell->NotifyMarkListChanged(m_pShell->GetFormView());
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::DetermineSelection(const SdrMarkList& rMarkList)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::DetermineSelection" );
+ if ( setCurrentSelectionFromMark( rMarkList ) && IsPropBrwOpen() )
+ ShowSelectionProperties( sal_True );
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmXFormShell::IsPropBrwOpen() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::IsPropBrwOpen" );
+ if ( impl_checkDisposed() )
+ return sal_False;
+
+ return( ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() ) ?
+ m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES) : sal_False );
+}
+
+//------------------------------------------------------------------------------
+class FmXFormShell::SuspendPropertyTracking
+{
+private:
+ FmXFormShell& m_rShell;
+ sal_Bool m_bEnabled;
+
+public:
+ SuspendPropertyTracking( FmXFormShell& _rShell )
+ :m_rShell( _rShell )
+ ,m_bEnabled( sal_False )
+ {
+ if ( m_rShell.IsTrackPropertiesEnabled() )
+ {
+ m_rShell.EnableTrackProperties( sal_False );
+ m_bEnabled = sal_True;
+ }
+ }
+
+ ~SuspendPropertyTracking( )
+ {
+ if ( m_bEnabled ) // note that ( sal_False != m_bEnabled ) implies ( NULL != m_pShell )
+ m_rShell.EnableTrackProperties( sal_True );
+ }
+};
+
+//------------------------------------------------------------------------------
+void FmXFormShell::SetDesignMode(sal_Bool bDesign)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetDesignMode" );
+ if ( impl_checkDisposed() )
+ return;
+
+ DBG_ASSERT(m_pShell->GetFormView(), "FmXFormShell::SetDesignMode : invalid call (have no shell or no view) !");
+ m_bChangingDesignMode = sal_True;
+
+ // 67506 - 15.07.99 - FS
+ // if we're switching off the design mode we have to force the property browser to be closed
+ // so it can commit it's changes _before_ we load the forms
+ if (!bDesign)
+ {
+ m_bHadPropertyBrowserInDesignMode = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES);
+ if (m_bHadPropertyBrowserInDesignMode)
+ m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES);
+ }
+
+ FmFormView* pFormView = m_pShell->GetFormView();
+ if (bDesign)
+ {
+ // we are currently filtering, so stop filtering
+ if (m_bFilterMode)
+ stopFiltering(sal_False);
+
+ // an den Objekten meiner MarkList als Listener abmelden
+ pFormView->GetImpl()->stopMarkListWatching();
+ }
+ else
+ {
+ m_aMarkTimer.Stop();
+
+ SuspendPropertyTracking aSuspend( *this );
+ pFormView->GetImpl()->saveMarkList( sal_True );
+ }
+
+ if (bDesign && m_xExternalViewController.is())
+ CloseExternalFormViewer();
+
+ pFormView->ChangeDesignMode(bDesign);
+
+ // Listener benachrichtigen
+ FmDesignModeChangedHint aChangedHint( bDesign );
+ m_pShell->Broadcast(aChangedHint);
+
+ m_pShell->m_bDesignMode = bDesign;
+ UpdateForms( sal_False );
+
+ m_pTextShell->designModeChanged( m_pShell->m_bDesignMode );
+
+ if (bDesign)
+ {
+ SdrMarkList aList;
+ {
+ // during changing the mark list, don't track the selected objects in the property browser
+ SuspendPropertyTracking aSuspend( *this );
+ // restore the marks
+ pFormView->GetImpl()->restoreMarkList( aList );
+ }
+
+ // synchronize with the restored mark list
+ if ( aList.GetMarkCount() )
+ SetSelection( aList );
+ }
+ else
+ {
+ // am Model der View als Listener anmelden (damit ich mitbekomme, wenn jemand waehrend des Alive-Modus
+ // Controls loescht, die ich eigentlich mit saveMarkList gespeichert habe) (60343)
+ pFormView->GetImpl()->startMarkListWatching();
+ }
+
+ m_pShell->UIFeatureChanged();
+
+ // 67506 - 15.07.99 - FS
+ if (bDesign && m_bHadPropertyBrowserInDesignMode)
+ {
+ // The UIFeatureChanged performes an update (a check of the available features) asynchronously.
+ // So we can't call ShowSelectionProperties directly as the according feature isn't enabled yet.
+ // That's why we use an asynchron execution on the dispatcher.
+ // (And that's why this has to be done AFTER the UIFeatureChanged.)
+ m_pShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON );
+ }
+ m_bChangingDesignMode = sal_False;
+}
+
+//------------------------------------------------------------------------------
+Reference< XControl> FmXFormShell::impl_getControl( const Reference< XControlModel >& i_rxModel, const FmFormObj& i_rKnownFormObj )
+{
+ if ( impl_checkDisposed() )
+ return NULL;
+
+ Reference< XControl > xControl;
+ try
+ {
+ Reference< XControlContainer> xControlContainer( getControlContainerForView(), UNO_SET_THROW );
+
+ Sequence< Reference< XControl > > seqControls( xControlContainer->getControls() );
+ const Reference< XControl >* pControls = seqControls.getArray();
+ // ... die ich dann durchsuchen kann
+ for (sal_Int32 i=0; i<seqControls.getLength(); ++i)
+ {
+ xControl.set( pControls[i], UNO_SET_THROW );
+ Reference< XControlModel > xCurrentModel( xControl->getModel() );
+ if ( xCurrentModel == i_rxModel )
+ break;
+ xControl.clear();
+ }
+
+ if ( !xControl.is() )
+ {
+ // fallabck (some controls might not have been created, yet, since they were never visible so far)
+ Reference< XControl > xContainerControl( xControlContainer, UNO_QUERY_THROW );
+ const Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerControl->getPeer() );
+ ENSURE_OR_THROW( pContainerWindow, "unexpected control container implementation" );
+
+ const SdrView* pSdrView = m_pShell ? m_pShell->GetFormView() : NULL;
+ ENSURE_OR_THROW( pSdrView, "no current view" );
+
+ xControl.set( i_rKnownFormObj.GetUnoControl( *pSdrView, *pContainerWindow ), UNO_QUERY_THROW );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ OSL_ENSURE( xControl.is(), "FmXFormShell::impl_getControl: no control found!" );
+ return xControl;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::impl_collectFormSearchContexts_nothrow( const Reference< XInterface>& _rxStartingPoint,
+ const ::rtl::OUString& _rCurrentLevelPrefix, FmFormArray& _out_rForms, ::std::vector< String >& _out_rNames )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::impl_collectFormSearchContexts_nothrow" );
+ try
+ {
+ Reference< XIndexAccess> xContainer( _rxStartingPoint, UNO_QUERY );
+ if ( !xContainer.is() )
+ return;
+
+ sal_Int32 nCount( xContainer->getCount() );
+ if ( nCount == 0 )
+ return;
+
+ ::rtl::OUString sCurrentFormName;
+ ::rtl::OUStringBuffer aNextLevelPrefix;
+ for ( sal_Int32 i=0; i<nCount; ++i )
+ {
+ // is the current child a form?
+ Reference< XForm > xCurrentAsForm( xContainer->getByIndex(i), UNO_QUERY );
+ if ( !xCurrentAsForm.is() )
+ continue;
+
+ Reference< XNamed > xNamed( xCurrentAsForm, UNO_QUERY_THROW );
+ sCurrentFormName = xNamed->getName();
+
+ // the name of the current form
+ ::rtl::OUStringBuffer sCompleteCurrentName( sCurrentFormName );
+ if ( _rCurrentLevelPrefix.getLength() )
+ {
+ sCompleteCurrentName.appendAscii( " (" );
+ sCompleteCurrentName.append ( _rCurrentLevelPrefix );
+ sCompleteCurrentName.appendAscii( ")" );
+ }
+
+ // the prefix for the next level
+ aNextLevelPrefix = _rCurrentLevelPrefix;
+ if ( _rCurrentLevelPrefix.getLength() )
+ aNextLevelPrefix.append( (sal_Unicode)'/' );
+ aNextLevelPrefix.append( sCurrentFormName );
+
+ // remember both the form and it's "display name"
+ _out_rForms.push_back( xCurrentAsForm );
+ _out_rNames.push_back( sCompleteCurrentName.makeStringAndClear() );
+
+ // und absteigen
+ impl_collectFormSearchContexts_nothrow( xCurrentAsForm, aNextLevelPrefix.makeStringAndClear(), _out_rForms, _out_rNames );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::startFiltering()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::startFiltering" );
+ if ( impl_checkDisposed() )
+ return;
+
+ // setting all forms in filter mode
+ FmXFormView* pXView = m_pShell->GetFormView()->GetImpl();
+
+ // if the active controller is our external one we have to use the trigger controller
+ Reference< XControlContainer> xContainer;
+ if (getActiveController() == m_xExternalViewController)
+ {
+ DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::startFiltering : inconsistent : active external controller, but noone triggered this !");
+ xContainer = m_xExtViewTriggerController->getContainer();
+ }
+ else
+ xContainer = getActiveController()->getContainer();
+
+ FmWinRecList::iterator i = pXView->findWindow(xContainer);
+ if (i != pXView->getWindowList().end())
+ {
+ const ::std::vector< Reference< runtime::XFormController> >& rControllerList = (*i)->GetList();
+ for (::std::vector< Reference< runtime::XFormController> >::const_iterator j = rControllerList.begin();
+ j != rControllerList.end(); ++j)
+ {
+ Reference< XModeSelector> xModeSelector(*j, UNO_QUERY);
+ if (xModeSelector.is())
+ xModeSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ) );
+ }
+ }
+
+ m_bFilterMode = sal_True;
+
+ m_pShell->UIFeatureChanged();
+ SfxViewFrame* pViewFrame = m_pShell->GetViewShell()->GetViewFrame();
+ pViewFrame->GetBindings().InvalidateShell( *m_pShell );
+
+ if ( pViewFrame->KnowsChildWindow( SID_FM_FILTER_NAVIGATOR )
+ && !pViewFrame->HasChildWindow( SID_FM_FILTER_NAVIGATOR )
+ )
+ {
+ pViewFrame->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
+ }
+}
+
+//------------------------------------------------------------------------------
+void saveFilter(const Reference< runtime::XFormController >& _rxController)
+{
+ Reference< XPropertySet> xFormAsSet(_rxController->getModel(), UNO_QUERY);
+ Reference< XPropertySet> xControllerAsSet(_rxController, UNO_QUERY);
+ Reference< XIndexAccess> xControllerAsIndex(_rxController, UNO_QUERY);
+
+ // call the subcontroller
+ Reference< runtime::XFormController > xController;
+ for (sal_Int32 i = 0, nCount = xControllerAsIndex->getCount(); i < nCount; ++i)
+ {
+ xControllerAsIndex->getByIndex(i) >>= xController;
+ saveFilter(xController);
+ }
+
+ try
+ {
+
+ xFormAsSet->setPropertyValue(FM_PROP_FILTER, xControllerAsSet->getPropertyValue(FM_PROP_FILTER));
+ xFormAsSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny( (sal_Bool)sal_True ) );
+ }
+ catch (const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::stopFiltering(sal_Bool bSave)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::stopFiltering" );
+ if ( impl_checkDisposed() )
+ return;
+
+ m_bFilterMode = sal_False;
+
+ FmXFormView* pXView = m_pShell->GetFormView()->GetImpl();
+
+ // if the active controller is our external one we have to use the trigger controller
+ Reference< XControlContainer> xContainer;
+ if (getActiveController() == m_xExternalViewController)
+ {
+ DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::stopFiltering : inconsistent : active external controller, but noone triggered this !");
+ xContainer = m_xExtViewTriggerController->getContainer();
+ }
+ else
+ xContainer = getActiveController()->getContainer();
+
+ FmWinRecList::iterator i = pXView->findWindow(xContainer);
+ if (i != pXView->getWindowList().end())
+ {
+ const ::std::vector< Reference< runtime::XFormController > >& rControllerList = (*i)->GetList();
+ ::std::vector < ::rtl::OUString > aOriginalFilters;
+ ::std::vector < sal_Bool > aOriginalApplyFlags;
+
+ if (bSave)
+ {
+ for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin();
+ j != rControllerList.end(); ++j)
+ {
+ if (bSave)
+ { // remember the current filter settings in case we're goin to reload the forms below (which may fail)
+ try
+ {
+ Reference< XPropertySet > xFormAsSet((*j)->getModel(), UNO_QUERY);
+ aOriginalFilters.push_back(::comphelper::getString(xFormAsSet->getPropertyValue(FM_PROP_FILTER)));
+ aOriginalApplyFlags.push_back(::comphelper::getBOOL(xFormAsSet->getPropertyValue(FM_PROP_APPLYFILTER)));
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmXFormShell::stopFiltering : could not get the original filter !");
+ // put dummies into the arrays so the they have the right size
+
+ if (aOriginalFilters.size() == aOriginalApplyFlags.size())
+ // the first getPropertyValue failed -> use two dummies
+ aOriginalFilters.push_back( ::rtl::OUString() );
+ aOriginalApplyFlags.push_back( sal_False );
+ }
+ }
+ saveFilter(*j);
+ }
+ }
+ for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin();
+ j != rControllerList.end(); ++j)
+ {
+
+ Reference< XModeSelector> xModeSelector(*j, UNO_QUERY);
+ if (xModeSelector.is())
+ xModeSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) );
+ }
+ if (bSave) // execute the filter
+ {
+ const ::std::vector< Reference< runtime::XFormController > > & rControllers = (*i)->GetList();
+ for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllers.begin();
+ j != rControllers.end(); ++j)
+ {
+ Reference< XLoadable> xReload((*j)->getModel(), UNO_QUERY);
+ if (!xReload.is())
+ continue;
+ Reference< XPropertySet > xFormSet(xReload, UNO_QUERY);
+
+ try
+ {
+ xReload->reload();
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmXFormShell::stopFiltering: Exception occurred!");
+ }
+
+ if (!isRowSetAlive(xFormSet))
+ { // something went wrong -> restore the original state
+ ::rtl::OUString sOriginalFilter = aOriginalFilters[ j - rControllers.begin() ];
+ sal_Bool bOriginalApplyFlag = aOriginalApplyFlags[ j - rControllers.begin() ];
+ try
+ {
+ xFormSet->setPropertyValue(FM_PROP_FILTER, makeAny(sOriginalFilter));
+ xFormSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny(bOriginalApplyFlag));
+ xReload->reload();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ }
+ }
+
+ m_pShell->UIFeatureChanged();
+ m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell);
+}
+
+//------------------------------------------------------------------------------
+void clearFilter(const Reference< runtime::XFormController >& _rxController)
+{
+ Reference< XPropertySet> xControllerAsSet(_rxController, UNO_QUERY);
+ Reference< XIndexAccess> xControllerAsIndex(_rxController, UNO_QUERY);
+
+ // call the subcontroller
+ Reference< runtime::XFormController > xController;
+ for (sal_Int32 i = 0, nCount = xControllerAsIndex->getCount();
+ i < nCount; i++)
+ {
+ xControllerAsIndex->getByIndex(i) >>= xController;
+ clearFilter(xController);
+ }
+
+ // clear the filter
+ Reference< XIndexContainer> xContainer;
+ xControllerAsSet->getPropertyValue(FM_PROP_FILTERSUPPLIER) >>= xContainer;
+ if (xContainer.is())
+ {
+ // clear the current filter
+ Sequence< PropertyValue> aCondition;
+
+ // as there is always an empty row, if we have a filter:
+ if (xContainer->getCount())
+ {
+ xControllerAsSet->setPropertyValue(FM_PROP_CURRENTFILTER, makeAny(sal_Int32(xContainer->getCount() - 1)));
+ while (xContainer->getCount() > 1)
+ xContainer->removeByIndex(0);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::clearFilter()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::clearFilter" );
+ if ( impl_checkDisposed() )
+ return;
+
+ FmXFormView* pXView = m_pShell->GetFormView()->GetImpl();
+
+ // if the active controller is our external one we have to use the trigger controller
+ Reference< XControlContainer> xContainer;
+ if (getActiveController() == m_xExternalViewController)
+ {
+ DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::clearFilter : inconsistent : active external controller, but noone triggered this !");
+ xContainer = m_xExtViewTriggerController->getContainer();
+ }
+ else
+ xContainer = getActiveController()->getContainer();
+
+ FmWinRecList::iterator i = pXView->findWindow(xContainer);
+ if (i != pXView->getWindowList().end())
+ {
+ const ::std::vector< Reference< runtime::XFormController > > & rControllerList = (*i)->GetList();
+ for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin();
+ j != rControllerList.end(); ++j)
+ {
+ ::clearFilter(*j);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::CreateExternalView()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::CreateExternalView" );
+ if ( impl_checkDisposed() )
+ return;
+
+ DBG_ASSERT(m_xAttachedFrame.is(), "FmXFormShell::CreateExternalView : no frame !");
+
+ // the frame the external view is displayed in
+ sal_Bool bAlreadyExistent = m_xExternalViewController.is();
+ Reference< ::com::sun::star::frame::XFrame> xExternalViewFrame;
+ ::rtl::OUString sFrameName(RTL_CONSTASCII_USTRINGPARAM("_beamer"));
+ sal_Int32 nSearchFlags = ::com::sun::star::frame::FrameSearchFlag::CHILDREN | ::com::sun::star::frame::FrameSearchFlag::CREATE;
+
+ Reference< runtime::XFormController > xCurrentNavController( getNavController());
+ // the creation of the "partwindow" may cause a deactivate of the document which will result in our nav controller to be set to NULL
+
+ // _first_ check if we have any valid fields we can use for the grid view
+ // FS - 21.10.99 - 69219
+ {
+ FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel());
+ Reference< XPropertySet> xCurrentModelSet;
+ sal_Bool bHaveUsableControls = sal_False;
+ while ((xCurrentModelSet = Reference< XPropertySet>(aModelIterator.Next(), UNO_QUERY)).is())
+ {
+ // the FmXBoundFormFieldIterator only supplies controls with a valid control source
+ // so we just have to check the field type
+ sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID));
+ switch (nClassId)
+ {
+ case FormComponentType::IMAGECONTROL:
+ case FormComponentType::CONTROL:
+ continue;
+ }
+ bHaveUsableControls = sal_True;
+ break;
+ }
+
+ if (!bHaveUsableControls)
+ {
+ ErrorBox(NULL, WB_OK, SVX_RESSTR(RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY)).Execute();
+ return;
+ }
+ }
+
+ // load the component for external form views
+ if (!bAlreadyExistent)
+ {
+ URL aWantToDispatch;
+ aWantToDispatch.Complete = FMURL_COMPONENT_FORMGRIDVIEW;
+
+ Reference< ::com::sun::star::frame::XDispatchProvider> xProv(m_xAttachedFrame, UNO_QUERY);
+ Reference< ::com::sun::star::frame::XDispatch> xDisp;
+ if (xProv.is())
+ xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags);
+ if (xDisp.is())
+ {
+ xDisp->dispatch(aWantToDispatch, Sequence< PropertyValue>());
+ }
+
+ // with this the component should be loaded, now search the frame where it resides in
+ xExternalViewFrame = m_xAttachedFrame->findFrame(sFrameName, ::com::sun::star::frame::FrameSearchFlag::CHILDREN);
+ if (xExternalViewFrame.is())
+ {
+ m_xExternalViewController = xExternalViewFrame->getController();
+ Reference< ::com::sun::star::lang::XComponent> xComp(m_xExternalViewController, UNO_QUERY);
+ if (xComp.is())
+ xComp->addEventListener((XEventListener*)(XPropertyChangeListener*)this);
+ }
+ }
+ else
+ {
+ xExternalViewFrame = m_xExternalViewController->getFrame();
+ Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
+
+ // if we display the active form we interpret the slot as "remove it"
+ Reference< XForm> xCurrentModel(xCurrentNavController->getModel(), UNO_QUERY);
+ if ((xCurrentModel == m_xExternalDisplayedForm) || (getInternalForm(xCurrentModel) == m_xExternalDisplayedForm))
+ {
+ if ( m_xExternalViewController == getActiveController() )
+ {
+ Reference< runtime::XFormController > xAsFormController( m_xExternalViewController, UNO_QUERY );
+ ControllerFeatures aHelper( ::comphelper::getProcessServiceFactory(), xAsFormController, NULL );
+ aHelper->commitCurrentControl();
+ }
+
+ Reference< runtime::XFormController > xNewController(m_xExtViewTriggerController);
+ CloseExternalFormViewer();
+ setActiveController(xNewController);
+ return;
+ }
+
+ URL aClearURL;
+ aClearURL.Complete = FMURL_GRIDVIEW_CLEARVIEW;
+
+ Reference< ::com::sun::star::frame::XDispatch> xClear( xCommLink->queryDispatch(aClearURL, ::rtl::OUString(), 0));
+ if (xClear.is())
+ xClear->dispatch(aClearURL, Sequence< PropertyValue>());
+ }
+
+ // TODO: We need an interceptor at the xSupplier, which forwards all queryDispatch requests to the FormController
+ // instance for which this "external view" was triggered
+
+ // get the dispatch interface of the frame so we can communicate (interceptable) with the controller
+ Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY);
+
+ if (m_xExternalViewController.is())
+ {
+ DBG_ASSERT(xCommLink.is(), "FmXFormShell::CreateExternalView : the component doesn't have the necessary interfaces !");
+ // collect the dispatchers we will need
+ URL aAddColumnURL;
+ aAddColumnURL.Complete = FMURL_GRIDVIEW_ADDCOLUMN;
+ Reference< ::com::sun::star::frame::XDispatch> xAddColumnDispatch( xCommLink->queryDispatch(aAddColumnURL, ::rtl::OUString(), 0));
+ URL aAttachURL;
+ aAttachURL.Complete = FMURL_GRIDVIEW_ATTACHTOFORM;
+ Reference< ::com::sun::star::frame::XDispatch> xAttachDispatch( xCommLink->queryDispatch(aAttachURL, ::rtl::OUString(), 0));
+
+ if (xAddColumnDispatch.is() && xAttachDispatch.is())
+ {
+ DBG_ASSERT(xCurrentNavController.is(), "FmXFormShell::CreateExternalView : invalid call : have no nav controller !");
+ // first : dispatch the descriptions for the columns to add
+ Sequence< Reference< XControl> > aCurrentControls(xCurrentNavController->getControls());
+
+ sal_Int16 nAddedColumns = 0;
+
+ // for radio buttons we need some special structures
+ DECLARE_STL_USTRINGACCESS_MAP(Sequence< ::rtl::OUString>, MapUString2UstringSeq);
+ DECLARE_STL_ITERATORS(MapUString2UstringSeq);
+ DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUString, FmMapUString2UString);
+ DECLARE_STL_USTRINGACCESS_MAP(sal_Int16, FmMapUString2Int16);
+ DECLARE_STL_ITERATORS(FmMapUString2Int16);
+
+ MapUString2UstringSeq aRadioValueLists;
+ MapUString2UstringSeq aRadioListSources;
+ FmMapUString2UString aRadioControlSources;
+ FmMapUString2Int16 aRadioPositions;
+
+ FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel());
+ Reference< XPropertySet> xCurrentModelSet;
+ Any aCurrentBoundField;
+ ::rtl::OUString sColumnType,aGroupName,sControlSource;
+ Sequence< Property> aProps;
+ Reference< XPropertySet> xCurrentBoundField;
+ while ((xCurrentModelSet = Reference< XPropertySet>(aModelIterator.Next(), UNO_QUERY)).is())
+ {
+ xCurrentModelSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xCurrentBoundField;
+ OSL_ENSURE(xCurrentModelSet.is(),"xCurrentModelSet is null!");
+ // create a description of the column to be created
+ // first : determine it's type
+
+ sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID));
+ switch (nClassId)
+ {
+ case FormComponentType::RADIOBUTTON:
+ {
+ // get the label of the button (this is the access key for our structures)
+ aGroupName = getLabelName(xCurrentModelSet);
+
+ // add the reference value of the radio button to the list source sequence
+ Sequence< ::rtl::OUString>& aThisGroupLabels = aRadioListSources[aGroupName];
+ sal_Int32 nNewSizeL = aThisGroupLabels.getLength() + 1;
+ aThisGroupLabels.realloc(nNewSizeL);
+ aThisGroupLabels.getArray()[nNewSizeL - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_REFVALUE));
+
+ // add the label to the value list sequence
+ Sequence< ::rtl::OUString>& aThisGroupControlSources = aRadioValueLists[aGroupName];
+ sal_Int32 nNewSizeC = aThisGroupControlSources.getLength() + 1;
+ aThisGroupControlSources.realloc(nNewSizeC);
+ aThisGroupControlSources.getArray()[nNewSizeC - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_LABEL));
+
+ // remember the controls source of the radio group
+ sControlSource = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_CONTROLSOURCE));
+ if (aRadioControlSources.find(aGroupName) == aRadioControlSources.end())
+ aRadioControlSources[aGroupName] = sControlSource;
+#ifdef DBG_UTIL
+ else
+ DBG_ASSERT(aRadioControlSources[aGroupName] == sControlSource,
+ "FmXFormShell::CreateExternalView : inconsistent radio buttons detected !");
+ // (radio buttons with the same name should have the same control source)
+#endif
+ // remember the position within the columns
+ if (aRadioPositions.find(aGroupName) == aRadioPositions.end())
+ aRadioPositions[aGroupName] = (sal_Int16)nAddedColumns;
+
+ // any further handling is done below
+ }
+ continue;
+
+ case FormComponentType::IMAGECONTROL:
+ case FormComponentType::CONTROL:
+ // no grid columns for these types (though they have a control source)
+ continue;
+ case FormComponentType::CHECKBOX:
+ sColumnType = FM_COL_CHECKBOX; break;
+ case FormComponentType::LISTBOX:
+ sColumnType = FM_COL_LISTBOX; break;
+ case FormComponentType::COMBOBOX:
+ sColumnType = FM_COL_COMBOBOX; break;
+ case FormComponentType::DATEFIELD:
+ sColumnType = FM_COL_DATEFIELD; break;
+ case FormComponentType::TIMEFIELD:
+ sColumnType = FM_COL_TIMEFIELD; break;
+ case FormComponentType::NUMERICFIELD:
+ sColumnType = FM_COL_NUMERICFIELD; break;
+ case FormComponentType::CURRENCYFIELD:
+ sColumnType = FM_COL_CURRENCYFIELD; break;
+ case FormComponentType::PATTERNFIELD:
+ sColumnType = FM_COL_PATTERNFIELD; break;
+
+ case FormComponentType::TEXTFIELD:
+ {
+ sColumnType = FM_COL_TEXTFIELD;
+ // we know at least two different controls which are TextFields : the basic edit field and the formatted
+ // field. we distinguish them by their service name
+ Reference< XServiceInfo> xInfo(xCurrentModelSet, UNO_QUERY);
+ if (xInfo.is())
+ {
+ sal_Int16 nObjectType = getControlTypeByObject(xInfo);
+ if (OBJ_FM_FORMATTEDFIELD == nObjectType)
+ sColumnType = FM_COL_FORMATTEDFIELD;
+ }
+ }
+ break;
+ default:
+ sColumnType = FM_COL_TEXTFIELD; break;
+ }
+
+ const sal_Int16 nDispatchArgs = 3;
+ Sequence< PropertyValue> aDispatchArgs(nDispatchArgs);
+ PropertyValue* pDispatchArgs = aDispatchArgs.getArray();
+
+ // properties describing "meta data" about the column
+ // the type
+ pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE;
+ pDispatchArgs->Value <<= sColumnType;
+ ++pDispatchArgs;
+
+ // the pos : append the col
+ pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS;
+ pDispatchArgs->Value <<= nAddedColumns;
+ ++pDispatchArgs;
+
+ // the properties to forward to the new column
+ Sequence< PropertyValue> aColumnProps(1);
+ PropertyValue* pColumnProps = aColumnProps.getArray();
+
+ // the label
+ pColumnProps->Name = FM_PROP_LABEL;
+ pColumnProps->Value <<= getLabelName(xCurrentModelSet);
+ ++pColumnProps;
+
+ // for all other props : transfer them
+ Reference< XPropertySetInfo> xControlModelInfo( xCurrentModelSet->getPropertySetInfo());
+ DBG_ASSERT(xControlModelInfo.is(), "FmXFormShell::CreateExternalView : the control model has no property info ! This will crash !");
+ aProps = xControlModelInfo->getProperties();
+ const Property* pProps = aProps.getConstArray();
+
+ // realloc the control description sequence
+ sal_Int32 nExistentDescs = pColumnProps - aColumnProps.getArray();
+ aColumnProps.realloc(nExistentDescs + aProps.getLength());
+ pColumnProps = aColumnProps.getArray() + nExistentDescs;
+
+ for (sal_Int32 i=0; i<aProps.getLength(); ++i, ++pProps)
+ {
+ if (pProps->Name.equals(FM_PROP_LABEL))
+ // already set
+ continue;
+ if (pProps->Name.equals(FM_PROP_DEFAULTCONTROL))
+ // allow the column's own "default control"
+ continue;
+ if (pProps->Attributes & PropertyAttribute::READONLY)
+ // assume that properties which are readonly for the control are ro for the column to be created, too
+ continue;
+
+ pColumnProps->Name = pProps->Name;
+ pColumnProps->Value = xCurrentModelSet->getPropertyValue(pProps->Name);
+ ++pColumnProps;
+ }
+ aColumnProps.realloc(pColumnProps - aColumnProps.getArray());
+
+ // columns props are a dispatch argument
+ pDispatchArgs->Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ColumnProperties")); // TODO : fmurl.*
+ pDispatchArgs->Value = makeAny(aColumnProps);
+ ++pDispatchArgs;
+ DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()),
+ "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
+
+ // dispatch the "add column"
+ xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs);
+ ++nAddedColumns;
+ }
+
+ // now for the radio button handling
+ sal_Int16 nOffset(0);
+ // properties describing the "direct" column properties
+ const sal_Int16 nListBoxDescription = 6;
+ Sequence< PropertyValue> aListBoxDescription(nListBoxDescription);
+ for ( ConstFmMapUString2UStringIterator aCtrlSource = aRadioControlSources.begin();
+ aCtrlSource != aRadioControlSources.end();
+ ++aCtrlSource, ++nOffset
+ )
+ {
+
+ PropertyValue* pListBoxDescription = aListBoxDescription.getArray();
+ // label
+ pListBoxDescription->Name = FM_PROP_LABEL;
+ pListBoxDescription->Value <<= (*aCtrlSource).first;
+ ++pListBoxDescription;
+
+ // control source
+ pListBoxDescription->Name = FM_PROP_CONTROLSOURCE;
+ pListBoxDescription->Value <<= (*aCtrlSource).second;
+ ++pListBoxDescription;
+
+ // bound column
+ pListBoxDescription->Name = FM_PROP_BOUNDCOLUMN;
+ pListBoxDescription->Value <<= (sal_Int16)1;
+ ++pListBoxDescription;
+
+ // content type
+ pListBoxDescription->Name = FM_PROP_LISTSOURCETYPE;
+ ListSourceType eType = ListSourceType_VALUELIST;
+ pListBoxDescription->Value = makeAny(eType);
+ ++pListBoxDescription;
+
+ // list source
+ MapUString2UstringSeq::const_iterator aCurrentListSource = aRadioListSources.find((*aCtrlSource).first);
+ DBG_ASSERT(aCurrentListSource != aRadioListSources.end(),
+ "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
+ pListBoxDescription->Name = FM_PROP_LISTSOURCE;
+ pListBoxDescription->Value = makeAny((*aCurrentListSource).second);
+ ++pListBoxDescription;
+
+ // value list
+ MapUString2UstringSeq::const_iterator aCurrentValueList = aRadioValueLists.find((*aCtrlSource).first);
+ DBG_ASSERT(aCurrentValueList != aRadioValueLists.end(),
+ "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
+ pListBoxDescription->Name = FM_PROP_STRINGITEMLIST;
+ pListBoxDescription->Value = makeAny(((*aCurrentValueList).second));
+ ++pListBoxDescription;
+
+ DBG_ASSERT(nListBoxDescription == (pListBoxDescription - aListBoxDescription.getConstArray()),
+ "FmXFormShell::CreateExternalView : forgot to adjust nListBoxDescription ?");
+
+ // properties describing the column "meta data"
+ const sal_Int16 nDispatchArgs = 3;
+ Sequence< PropertyValue> aDispatchArgs(nDispatchArgs);
+ PropertyValue* pDispatchArgs = aDispatchArgs.getArray();
+
+ // column type : listbox
+ pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE;
+ ::rtl::OUString fColName = FM_COL_LISTBOX;
+ pDispatchArgs->Value <<= fColName;
+// pDispatchArgs->Value <<= (::rtl::OUString)FM_COL_LISTBOX;
+ ++pDispatchArgs;
+
+ // column position
+ pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS;
+ FmMapUString2Int16::const_iterator aOffset = aRadioPositions.find((*aCtrlSource).first);
+ DBG_ASSERT(aOffset != aRadioPositions.end(),
+ "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
+ sal_Int16 nPosition = (*aOffset).second;
+ nPosition = nPosition + nOffset;
+ // we alread inserted nOffset additinal columns ....
+ pDispatchArgs->Value <<= nPosition;
+ ++pDispatchArgs;
+
+ // the
+ pDispatchArgs->Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ColumnProperties")); // TODO : fmurl.*
+ pDispatchArgs->Value = makeAny(aListBoxDescription);
+ ++pDispatchArgs;
+ DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()),
+ "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
+
+ // dispatch the "add column"
+ xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs);
+ ++nAddedColumns;
+ }
+
+
+ DBG_ASSERT(nAddedColumns > 0, "FmXFormShell::CreateExternalView : no controls (inconsistent) !");
+ // we should have checked if we have any usable controls (see above).
+
+ // "load" the "form" of the external view
+ PropertyValue aArg;
+ aArg.Name = FMARG_ATTACHTO_MASTERFORM;
+ Reference< XResultSet> xForm(xCurrentNavController->getModel(), UNO_QUERY);
+ aArg.Value <<= xForm;
+
+ m_xExternalDisplayedForm = Reference< XResultSet>(xForm, UNO_QUERY);
+ // do this before dispatching the "attach" command, as the atach may result in a call to our queryDispatch (for the FormSlots)
+ // whichs needs the m_xExternalDisplayedForm
+
+ xAttachDispatch->dispatch(aAttachURL, Sequence< PropertyValue>(&aArg, 1));
+
+ m_xExtViewTriggerController = xCurrentNavController;
+
+ // we want to know modifications done in the external view
+ // if the external controller is a XFormController we can use all our default handlings for it
+ Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY );
+ OSL_ENSURE( xFormController.is(), "FmXFormShell::CreateExternalView:: invalid external view controller!" );
+ if (xFormController.is())
+ xFormController->addActivateListener((XFormControllerListener*)this);
+ }
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR("FmXFormShell::CreateExternalView : could not create the external form view !");
+ }
+#endif
+ InvalidateSlot( SID_FM_VIEW_AS_GRID, sal_False );
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::implAdjustConfigCache()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::implAdjustConfigCache" );
+ // get (cache) the wizard usage flag
+ Sequence< ::rtl::OUString > aNames(1);
+ aNames[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FormControlPilotsEnabled"));
+ Sequence< Any > aFlags = GetProperties(aNames);
+ if (1 == aFlags.getLength())
+ m_bUseWizards = ::cppu::any2bool(aFlags[0]);
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::Notify( const com::sun::star::uno::Sequence< rtl::OUString >& _rPropertyNames)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::Notify" );
+ if ( impl_checkDisposed() )
+ return;
+
+ const ::rtl::OUString* pSearch = _rPropertyNames.getConstArray();
+ const ::rtl::OUString* pSearchTil = pSearch + _rPropertyNames.getLength();
+ for (;pSearch < pSearchTil; ++pSearch)
+ if (0 == pSearch->compareToAscii("FormControlPilotsEnabled"))
+ {
+ implAdjustConfigCache();
+ InvalidateSlot( SID_FM_USE_WIZARDS, sal_True );
+ }
+}
+
+void FmXFormShell::Commit()
+{
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::SetWizardUsing(sal_Bool _bUseThem)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetWizardUsing" );
+ m_bUseWizards = _bUseThem;
+
+ Sequence< ::rtl::OUString > aNames(1);
+ aNames[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FormControlPilotsEnabled"));
+ Sequence< Any > aValues(1);
+ aValues[0] = ::cppu::bool2any(m_bUseWizards);
+ PutProperties(aNames, aValues);
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::viewDeactivated( FmFormView& _rCurrentView, sal_Bool _bDeactivateController /* = sal_True */ )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::viewDeactivated" );
+
+ if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() )
+ {
+ _rCurrentView.GetImpl()->Deactivate( _bDeactivateController );
+ }
+
+ // if we have an async load operation pending for the 0-th page for this view,
+ // we need to cancel this
+ // 103727 - 2002-09-26 - fs@openoffice.org
+ FmFormPage* pPage = _rCurrentView.GetCurPage();
+ if ( pPage )
+ {
+ // move all events from our queue to a new one, omit the events for the deactivated
+ // page
+ ::std::queue< FmLoadAction > aNewEvents;
+ while ( m_aLoadingPages.size() )
+ {
+ FmLoadAction aAction = m_aLoadingPages.front();
+ m_aLoadingPages.pop();
+ if ( pPage != aAction.pPage )
+ {
+ aNewEvents.push( aAction );
+ }
+ else
+ {
+ Application::RemoveUserEvent( aAction.nEventId );
+ }
+ }
+ m_aLoadingPages = aNewEvents;
+ }
+
+ // remove callbacks at the page
+ if ( pPage )
+ {
+ pPage->GetImpl().SetFormsCreationHdl( Link() );
+ }
+ UpdateForms( sal_True );
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmXFormShell, OnFirstTimeActivation, void*, /*NOTINTERESTEDIN*/ )
+{
+ if ( impl_checkDisposed() )
+ return 0L;
+
+ m_nActivationEvent = 0;
+ SfxObjectShell* pDocument = m_pShell->GetObjectShell();
+
+ if ( pDocument && !pDocument->HasName() )
+ {
+ if ( isEnhancedForm() )
+ {
+ // show the data navigator
+ if ( !m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_DATANAVIGATOR ) )
+ m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_SHOW_DATANAVIGATOR );
+ }
+ }
+
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmXFormShell, OnFormsCreated, FmFormPage*, /*_pPage*/ )
+{
+ UpdateForms( sal_True );
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::viewActivated( FmFormView& _rCurrentView, sal_Bool _bSyncAction /* = sal_False */ )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::viewActivated" );
+
+ FmFormPage* pPage = _rCurrentView.GetCurPage();
+
+ // activate our view if we are activated ourself
+ // FS - 30.06.99 - 67308
+ if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() )
+ {
+ // load forms for the page the current view belongs to
+ if ( pPage )
+ {
+ if ( !pPage->GetImpl().hasEverBeenActivated() )
+ loadForms( pPage, FORMS_LOAD | ( _bSyncAction ? FORMS_SYNC : FORMS_ASYNC ) );
+ pPage->GetImpl().setHasBeenActivated( );
+ }
+
+ // first-time initializations for the views
+ if ( !_rCurrentView.GetImpl()->hasEverBeenActivated( ) )
+ {
+ _rCurrentView.GetImpl()->onFirstViewActivation( PTR_CAST( FmFormModel, _rCurrentView.GetModel() ) );
+ _rCurrentView.GetImpl()->setHasBeenActivated( );
+ }
+
+ // activate the current view
+ _rCurrentView.GetImpl()->Activate( _bSyncAction );
+ }
+
+ // set callbacks at the page
+ if ( pPage )
+ {
+ pPage->GetImpl().SetFormsCreationHdl( LINK( this, FmXFormShell, OnFormsCreated ) );
+ }
+
+ UpdateForms( sal_True );
+
+ if ( !hasEverBeenActivated() )
+ {
+ m_nActivationEvent = Application::PostUserEvent( LINK( this, FmXFormShell, OnFirstTimeActivation ) );
+ setHasBeenActivated();
+ }
+
+ // find a default "current form", if there is none, yet
+ // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
+ impl_defaultCurrentForm_nothrow();
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::impl_defaultCurrentForm_nothrow()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::impl_defaultCurrentForm_nothrow" );
+ if ( impl_checkDisposed() )
+ return;
+
+ if ( m_xCurrentForm.is() )
+ // no action required
+ return;
+
+ FmFormView* pFormView = m_pShell->GetFormView();
+ FmFormPage* pPage = pFormView ? pFormView->GetCurPage() : NULL;
+ if ( !pPage )
+ return;
+
+ try
+ {
+ Reference< XIndexAccess > xForms( pPage->GetForms( false ), UNO_QUERY );
+ if ( !xForms.is() || !xForms->hasElements() )
+ return;
+
+ Reference< XForm > xNewCurrentForm( xForms->getByIndex(0), UNO_QUERY_THROW );
+ impl_updateCurrentForm( xNewCurrentForm );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormShell::smartControlReset( const Reference< XIndexAccess >& _rxModels )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::smartControlReset" );
+ if (!_rxModels.is())
+ {
+ DBG_ERROR("FmXFormShell::smartControlReset: invalid container!");
+ return;
+ }
+
+ static const ::rtl::OUString sClassIdPropertyName = FM_PROP_CLASSID;
+ static const ::rtl::OUString sBoundFieldPropertyName = FM_PROP_BOUNDFIELD;
+ sal_Int32 nCount = _rxModels->getCount();
+ Reference< XPropertySet > xCurrent;
+ Reference< XPropertySetInfo > xCurrentInfo;
+ Reference< XPropertySet > xBoundField;
+
+ for (sal_Int32 i=0; i<nCount; ++i)
+ {
+ _rxModels->getByIndex(i) >>= xCurrent;
+ if (xCurrent.is())
+ xCurrentInfo = xCurrent->getPropertySetInfo();
+ else
+ xCurrentInfo.clear();
+ if (!xCurrentInfo.is())
+ continue;
+
+ if (xCurrentInfo->hasPropertyByName(sClassIdPropertyName))
+ { // it's a control model
+
+ // check if this control is bound to a living database field
+ if (xCurrentInfo->hasPropertyByName(sBoundFieldPropertyName))
+ xCurrent->getPropertyValue(sBoundFieldPropertyName) >>= xBoundField;
+ else
+ xBoundField.clear();
+
+ // reset only if it's *not* bound
+ bool bReset = !xBoundField.is();
+
+ // and additionally, check if it has an external value binding
+ Reference< XBindableValue > xBindable( xCurrent, UNO_QUERY );
+ if ( xBindable.is() && xBindable->getValueBinding().is() )
+ bReset = false;
+
+ if ( bReset )
+ {
+ Reference< XReset > xControlReset( xCurrent, UNO_QUERY );
+ if ( xControlReset.is() )
+ xControlReset->reset();
+ }
+ }
+ else
+ {
+ Reference< XIndexAccess > xContainer(xCurrent, UNO_QUERY);
+ if (xContainer.is())
+ smartControlReset(xContainer);
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmXFormShell, OnLoadForms, FmFormPage*, /*_pPage*/ )
+{
+ FmLoadAction aAction = m_aLoadingPages.front();
+ m_aLoadingPages.pop();
+
+ loadForms( aAction.pPage, aAction.nFlags & ~FORMS_ASYNC );
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ sal_Bool lcl_isLoadable( const Reference< XInterface >& _rxLoadable )
+ {
+ // determines whether a form should be loaded or not
+ // if there is no datasource or connection there is no reason to load a form
+ Reference< XPropertySet > xSet( _rxLoadable, UNO_QUERY );
+ if ( !xSet.is() )
+ return sal_False;
+ try
+ {
+ Reference< XConnection > xConn;
+ if ( OStaticDataAccessTools().isEmbeddedInDatabase( _rxLoadable.get(), xConn ) )
+ return sal_True;
+
+ // is there already a active connection
+ xSet->getPropertyValue(FM_PROP_ACTIVE_CONNECTION) >>= xConn;
+ if ( xConn.is() )
+ return sal_True;
+
+ ::rtl::OUString sPropertyValue;
+ OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DATASOURCE ) >>= sPropertyValue );
+ if ( sPropertyValue.getLength() )
+ return sal_True;
+
+ OSL_VERIFY( xSet->getPropertyValue( FM_PROP_URL ) >>= sPropertyValue );
+ if ( sPropertyValue.getLength() )
+ return sal_True;
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return sal_False;
+ }
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::loadForms( FmFormPage* _pPage, const sal_uInt16 _nBehaviour /* FORMS_LOAD | FORMS_SYNC */ )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::loadForms" );
+ DBG_ASSERT( ( _nBehaviour & ( FORMS_ASYNC | FORMS_UNLOAD ) ) != ( FORMS_ASYNC | FORMS_UNLOAD ),
+ "FmXFormShell::loadForms: async loading not supported - this will heavily fail!" );
+
+ if ( _nBehaviour & FORMS_ASYNC )
+ {
+ m_aLoadingPages.push( FmLoadAction(
+ _pPage,
+ _nBehaviour,
+ Application::PostUserEvent( LINK( this, FmXFormShell, OnLoadForms ), _pPage )
+ ) );
+ return;
+ }
+
+ DBG_ASSERT( _pPage, "FmXFormShell::loadForms: invalid page!" );
+ if ( _pPage )
+ {
+ // lock the undo env so the forms can change non-transient properties while loading
+ // (without this my doc's modified flag would be set)
+ FmFormModel* pModel = PTR_CAST( FmFormModel, _pPage->GetModel() );
+ DBG_ASSERT( pModel, "FmXFormShell::loadForms: invalid model!" );
+ if ( pModel )
+ pModel->GetUndoEnv().Lock();
+
+ // load all forms
+ Reference< XIndexAccess > xForms;
+ xForms = xForms.query( _pPage->GetForms( false ) );
+
+ if ( xForms.is() )
+ {
+ Reference< XLoadable > xForm;
+ sal_Bool bFormWasLoaded = sal_False;
+ for ( sal_Int32 j = 0, nCount = xForms->getCount(); j < nCount; ++j )
+ {
+ xForms->getByIndex( j ) >>= xForm;
+ bFormWasLoaded = sal_False;
+ // a database form must be loaded for
+ try
+ {
+ if ( 0 == ( _nBehaviour & FORMS_UNLOAD ) )
+ {
+ if ( lcl_isLoadable( xForm ) && !xForm->isLoaded() )
+ xForm->load();
+ }
+ else
+ {
+ if ( xForm->isLoaded() )
+ {
+ bFormWasLoaded = sal_True;
+ xForm->unload();
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // reset the form if it was loaded
+ if ( bFormWasLoaded )
+ {
+ Reference< XIndexAccess > xContainer( xForm, UNO_QUERY );
+ DBG_ASSERT( xContainer.is(), "FmXFormShell::loadForms: the form is no container!" );
+ if ( xContainer.is() )
+ smartControlReset( xContainer );
+ }
+ }
+ }
+
+ if ( pModel )
+ // unlock the environment
+ pModel->GetUndoEnv().UnLock();
+ }
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::ExecuteTextAttribute( SfxRequest& _rReq )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ExecuteTextAttribute" );
+ m_pTextShell->ExecuteTextAttribute( _rReq );
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::GetTextAttributeState( SfxItemSet& _rSet )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::GetTextAttributeState" );
+ m_pTextShell->GetTextAttributeState( _rSet );
+}
+
+//------------------------------------------------------------------------
+bool FmXFormShell::IsActiveControl( bool _bCountRichTextOnly ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::IsActiveControl" );
+ return m_pTextShell->IsActiveControl( _bCountRichTextOnly );
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::ForgetActiveControl()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::ForgetActiveControl" );
+ m_pTextShell->ForgetActiveControl();
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::SetControlActivationHandler( const Link& _rHdl )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::SetControlActivationHandler" );
+ m_pTextShell->SetControlActivationHandler( _rHdl );
+}
+//------------------------------------------------------------------------
+void FmXFormShell::handleShowPropertiesRequest()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::handleShowPropertiesRequest" );
+ if ( onlyControlsAreMarked() )
+ ShowSelectionProperties( sal_True );
+}
+
+//------------------------------------------------------------------------
+void FmXFormShell::handleMouseButtonDown( const SdrViewEvent& _rViewEvent )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormShell::handleMouseButtonDown" );
+ // catch simple double clicks
+ if ( ( _rViewEvent.nMouseClicks == 2 ) && ( _rViewEvent.nMouseCode == MOUSE_LEFT ) )
+ {
+ if ( _rViewEvent.eHit == SDRHIT_MARKEDOBJECT )
+ {
+ if ( onlyControlsAreMarked() )
+ ShowSelectionProperties( sal_True );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+bool FmXFormShell::HasControlFocus() const
+{
+ bool bHasControlFocus = false;
+
+ try
+ {
+ Reference< XFormController > xController( getActiveController() );
+ Reference< XControl > xCurrentControl;
+ if ( xController.is() )
+ xCurrentControl.set( xController->getCurrentControl() );
+ if ( xCurrentControl.is() )
+ {
+ Reference< XWindow2 > xPeerWindow( xCurrentControl->getPeer(), UNO_QUERY_THROW );
+ bHasControlFocus = xPeerWindow->hasFocus();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return bHasControlFocus;
+}
+
+//==============================================================================
+//==============================================================================
+SearchableControlIterator::SearchableControlIterator(Reference< XInterface> xStartingPoint)
+ :IndexAccessIterator(xStartingPoint)
+{
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SearchableControlIterator::ShouldHandleElement(const Reference< XInterface>& xElement)
+{
+ // wenn das Ding eine ControlSource und einen BoundField-Property hat
+ Reference< XPropertySet> xProperties(xElement, UNO_QUERY);
+ if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xProperties) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xProperties))
+ {
+ // und das BoundField gueltig ist
+ Reference< XPropertySet> xField;
+ xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+ if (xField.is())
+ {
+ // nehmen wir's
+ m_sCurrentValue = ::comphelper::getString(xProperties->getPropertyValue(FM_PROP_CONTROLSOURCE));
+ return sal_True;
+ }
+ }
+
+ // wenn es ein Grid-Control ist
+ if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
+ {
+ Any aClassId( xProperties->getPropertyValue(FM_PROP_CLASSID) );
+ if (::comphelper::getINT16(aClassId) == FormComponentType::GRIDCONTROL)
+ {
+ m_sCurrentValue = ::rtl::OUString();
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SearchableControlIterator::ShouldStepInto(const Reference< XInterface>& /*xContainer*/) const
+{
+ return sal_True;
+}
+
+//==============================================================================
+//==============================================================================
+
+SV_IMPL_PTRARR(StatusForwarderArray, SfxStatusForwarder*)
+
+SFX_IMPL_MENU_CONTROL(ControlConversionMenuController, SfxBoolItem);
+
+//------------------------------------------------------------------------------
+ControlConversionMenuController::ControlConversionMenuController( sal_uInt16 _nId, Menu& _rMenu, SfxBindings& _rBindings )
+ :SfxMenuControl( _nId, _rBindings )
+ ,m_pMainMenu( &_rMenu )
+ ,m_pConversionMenu( NULL )
+{
+ if ( _nId == SID_FM_CHANGECONTROLTYPE )
+ {
+ m_pConversionMenu = FmXFormShell::GetConversionMenu();
+ _rMenu.SetPopupMenu( _nId, m_pConversionMenu );
+
+ for (sal_Int16 i=0; i<m_pConversionMenu->GetItemCount(); ++i)
+ {
+ _rBindings.Invalidate(m_pConversionMenu->GetItemId(i));
+ SfxStatusForwarder* pForwarder = new SfxStatusForwarder(m_pConversionMenu->GetItemId(i), *this);
+ m_aStatusForwarders.C40_INSERT(SfxStatusForwarder, pForwarder, m_aStatusForwarders.Count());
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+ControlConversionMenuController::~ControlConversionMenuController()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "ControlConversionMenuController::~ControlConversionMenuController" );
+ m_pMainMenu->SetPopupMenu(SID_FM_CHANGECONTROLTYPE, NULL);
+ delete m_pConversionMenu;
+}
+
+//------------------------------------------------------------------------------
+void ControlConversionMenuController::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
+{
+ if (nSID == GetId())
+ SfxMenuControl::StateChanged(nSID, eState, pState);
+ else if (FmXFormShell::isControlConversionSlot(nSID))
+ {
+ if ((m_pConversionMenu->GetItemPos(nSID) != MENU_ITEM_NOTFOUND) && (eState == SFX_ITEM_DISABLED))
+ {
+ m_pConversionMenu->RemoveItem(m_pConversionMenu->GetItemPos(nSID));
+ }
+ else if ((m_pConversionMenu->GetItemPos(nSID) == MENU_ITEM_NOTFOUND) && (eState != SFX_ITEM_DISABLED))
+ {
+ // We can't simply re-insert the item because we have a clear order for all the our items.
+ // So first we have to determine the position of the item to insert.
+ PopupMenu* pSource = FmXFormShell::GetConversionMenu();
+ USHORT nSourcePos = pSource->GetItemPos(nSID);
+ DBG_ASSERT(nSourcePos != MENU_ITEM_NOTFOUND, "ControlConversionMenuController::StateChanged : FmXFormShell supplied an invalid menu !");
+ USHORT nPrevInSource = nSourcePos;
+ USHORT nPrevInConversion = MENU_ITEM_NOTFOUND;
+ while (nPrevInSource>0)
+ {
+ sal_Int16 nPrevId = pSource->GetItemId(--nPrevInSource);
+
+ // do we have the source's predecessor in our conversion menu, too ?
+ nPrevInConversion = m_pConversionMenu->GetItemPos(nPrevId);
+ if (nPrevInConversion != MENU_ITEM_NOTFOUND)
+ break;
+ }
+ if (MENU_ITEM_NOTFOUND == nPrevInConversion)
+ // none of the items which precede the nSID-slot in the source menu are present in our conversion menu
+ nPrevInConversion = sal::static_int_cast< USHORT >(-1); // put the item at the first position
+ m_pConversionMenu->InsertItem(nSID, pSource->GetItemText(nSID), pSource->GetItemBits(nSID), ++nPrevInConversion);
+ m_pConversionMenu->SetItemImage(nSID, pSource->GetItemImage(nSID));
+ m_pConversionMenu->SetHelpId(nSID, pSource->GetHelpId(nSID));
+
+ delete pSource;
+ }
+ m_pMainMenu->EnableItem(SID_FM_CHANGECONTROLTYPE, m_pConversionMenu->GetItemCount() > 0);
+ }
+ else
+ {
+ DBG_ERROR("ControlConversionMenuController::StateChanged : unknown id !");
+ }
+}
+
+//==============================================================================
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmsrccfg.cxx b/svx/source/form/fmsrccfg.cxx
new file mode 100644
index 000000000000..089c123f5e78
--- /dev/null
+++ b/svx/source/form/fmsrccfg.cxx
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmsrccfg.hxx"
+#include <svl/filerec.hxx>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <comphelper/processfactory.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::i18n;
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ // ====================================================================
+ // = struct FmSearchParams - Parameter einer Suche
+ // ====================================================================
+
+ FmSearchParams::FmSearchParams()
+ :nTransliterationFlags( 0 )
+ ,nSearchForType ( 0 )
+ ,nPosition ( MATCHING_ANYWHERE )
+ ,nLevOther ( 2 )
+ ,nLevShorter ( 2 )
+ ,nLevLonger ( 2 )
+ ,bLevRelaxed ( sal_True )
+ ,bAllFields ( sal_False )
+ ,bUseFormatter ( sal_True )
+ ,bBackwards ( sal_False )
+ ,bWildcard ( sal_False )
+ ,bRegular ( sal_False )
+ ,bApproxSearch ( sal_False )
+ ,bSoundsLikeCJK ( sal_False )
+ {
+ nTransliterationFlags =
+ TransliterationModules_ignoreSpace_ja_JP
+ | TransliterationModules_ignoreMiddleDot_ja_JP
+ | TransliterationModules_ignoreProlongedSoundMark_ja_JP
+ | TransliterationModules_ignoreSeparator_ja_JP
+ | TransliterationModules_IGNORE_CASE;
+ }
+
+ sal_Bool FmSearchParams::isIgnoreWidthCJK( ) const
+ {
+ return 0 != (nTransliterationFlags & TransliterationModules_IGNORE_WIDTH);
+ }
+
+ void FmSearchParams::setIgnoreWidthCJK( sal_Bool _bIgnore )
+ {
+ if ( _bIgnore )
+ nTransliterationFlags |= TransliterationModules_IGNORE_WIDTH;
+ else
+ nTransliterationFlags &= ~TransliterationModules_IGNORE_WIDTH;
+ }
+
+ sal_Bool FmSearchParams::isCaseSensitive( ) const
+ {
+ return 0 == (nTransliterationFlags & TransliterationModules_IGNORE_CASE);
+ }
+
+ void FmSearchParams::setCaseSensitive( sal_Bool _bCase )
+ {
+ if ( _bCase )
+ nTransliterationFlags &= ~TransliterationModules_IGNORE_CASE;
+ else
+ nTransliterationFlags |= TransliterationModules_IGNORE_CASE;
+ }
+
+ // ====================================================================
+ // = maps from ascii values to int values
+ // ====================================================================
+
+ struct Ascii2Int16
+ {
+ const sal_Char* pAscii;
+ sal_Int16 nValue;
+ };
+
+ static const Ascii2Int16* lcl_getSearchForTypeValueMap()
+ {
+ static const Ascii2Int16 s_aSearchForTypeMap[] =
+ {
+ { "text", 0 },
+ { "null", 1 },
+ { "non-null", 2 },
+ { NULL, -1 }
+ };
+ return s_aSearchForTypeMap;
+ }
+
+ static const Ascii2Int16* lcl_getSearchPositionValueMap()
+ {
+ static const Ascii2Int16 s_aSearchPositionMap[] =
+ {
+ { "anywhere-in-field", MATCHING_ANYWHERE },
+ { "beginning-of-field", MATCHING_BEGINNING },
+ { "end-of-field", MATCHING_END },
+ { "complete-field", MATCHING_WHOLETEXT },
+ { NULL, -1 }
+ };
+ return s_aSearchPositionMap;
+ }
+
+ static sal_Int16 lcl_implMapAsciiValue( const ::rtl::OUString& _rAsciiValue, const Ascii2Int16* _pMap )
+ {
+ // search the map for the given ascii value
+ const Ascii2Int16* pSearch = _pMap;
+ while ( pSearch && pSearch->pAscii )
+ {
+ if ( 0 == _rAsciiValue.compareToAscii( pSearch->pAscii ) )
+ // found
+ return pSearch->nValue;
+ ++pSearch;
+ }
+
+ DBG_ERROR(
+ ( ::rtl::OString( "lcl_implMapAsciiValue: could not convert the ascii value " )
+ += ::rtl::OString( _rAsciiValue.getStr(), _rAsciiValue.getLength(), RTL_TEXTENCODING_ASCII_US )
+ += ::rtl::OString( " !" )
+ ).getStr()
+ );
+ return -1;
+ }
+
+ static const sal_Char* lcl_implMapIntValue( const sal_Int16 _nValue, const Ascii2Int16* _pMap )
+ {
+ // search the map for the given integer value
+ const Ascii2Int16* pSearch = _pMap;
+ while ( pSearch && pSearch->pAscii )
+ {
+ if ( _nValue == pSearch->nValue )
+ // found
+ return pSearch->pAscii;
+ ++pSearch;
+ }
+
+ DBG_ERROR(
+ ( ::rtl::OString( "lcl_implMapIntValue: could not convert the integer value " )
+ += ::rtl::OString::valueOf( (sal_Int32)_nValue )
+ += ::rtl::OString( " !" )
+ ).getStr()
+ );
+ static const sal_Char* s_pDummy = "";
+ // just as a fallback ....
+ return s_pDummy;
+ }
+
+ // ====================================================================
+ // = class FmSearchConfigItem - ein ConfigItem, dass sich Suchparameter merkt
+ // ====================================================================
+
+#define TA( c ) &c, getCppuType( &c )
+
+ FmSearchConfigItem::FmSearchConfigItem()
+ :OConfigurationValueContainer( ::comphelper::getProcessServiceFactory(), m_aMutex, "/org.openoffice.Office.DataAccess/FormSearchOptions", CVC_UPDATE_ACCESS | CVC_LAZY_UPDATE, 2 )
+ {
+ // register our members so the data exchange with the node values is done automatically
+
+ registerExchangeLocation( "SearchHistory", TA( aHistory ) );
+ registerExchangeLocation( "LevenshteinOther", TA( nLevOther ) );
+ registerExchangeLocation( "LevenshteinShorter", TA( nLevShorter ) );
+ registerExchangeLocation( "LevenshteinLonger", TA( nLevLonger ) );
+ registerExchangeLocation( "IsLevenshteinRelaxed", TA( bLevRelaxed ) );
+ registerExchangeLocation( "IsSearchAllFields", TA( bAllFields ) );
+ registerExchangeLocation( "IsUseFormatter", TA( bUseFormatter ) );
+ registerExchangeLocation( "IsBackwards", TA( bBackwards ) );
+ registerExchangeLocation( "IsWildcardSearch", TA( bWildcard ) );
+ registerExchangeLocation( "IsUseRegularExpression", TA( bRegular ) );
+ registerExchangeLocation( "IsSimilaritySearch", TA( bApproxSearch ) );
+ registerExchangeLocation( "IsUseAsianOptions", TA( bSoundsLikeCJK ) );
+
+ // the properties which need to be translated
+ registerExchangeLocation( "SearchType", TA( m_sSearchForType ) );
+ registerExchangeLocation( "SearchPosition", TA( m_sSearchPosition ) );
+
+ registerExchangeLocation( "IsMatchCase", TA( m_bIsMatchCase ) );
+ registerExchangeLocation( "Japanese/IsMatchFullHalfWidthForms", TA( m_bIsMatchFullHalfWidthForms ) );
+ registerExchangeLocation( "Japanese/IsMatchHiraganaKatakana", TA( m_bIsMatchHiraganaKatakana ) );
+ registerExchangeLocation( "Japanese/IsMatchContractions", TA( m_bIsMatchContractions ) );
+ registerExchangeLocation( "Japanese/IsMatchMinusDashCho-on", TA( m_bIsMatchMinusDashCho_on ) );
+ registerExchangeLocation( "Japanese/IsMatchRepeatCharMarks", TA( m_bIsMatchRepeatCharMarks ) );
+ registerExchangeLocation( "Japanese/IsMatchVariantFormKanji", TA( m_bIsMatchVariantFormKanji ) );
+ registerExchangeLocation( "Japanese/IsMatchOldKanaForms", TA( m_bIsMatchOldKanaForms ) );
+ registerExchangeLocation( "Japanese/IsMatch_DiZi_DuZu", TA( m_bIsMatch_DiZi_DuZu ) );
+ registerExchangeLocation( "Japanese/IsMatch_BaVa_HaFa", TA( m_bIsMatch_BaVa_HaFa ) );
+ registerExchangeLocation( "Japanese/IsMatch_TsiThiChi_DhiZi", TA( m_bIsMatch_TsiThiChi_DhiZi ) );
+ registerExchangeLocation( "Japanese/IsMatch_HyuIyu_ByuVyu", TA( m_bIsMatch_HyuIyu_ByuVyu ) );
+ registerExchangeLocation( "Japanese/IsMatch_SeShe_ZeJe", TA( m_bIsMatch_SeShe_ZeJe ) );
+ registerExchangeLocation( "Japanese/IsMatch_IaIya", TA( m_bIsMatch_IaIya ) );
+ registerExchangeLocation( "Japanese/IsMatch_KiKu", TA( m_bIsMatch_KiKu ) );
+ registerExchangeLocation( "Japanese/IsIgnorePunctuation", TA( m_bIsIgnorePunctuation ) );
+ registerExchangeLocation( "Japanese/IsIgnoreWhitespace", TA( m_bIsIgnoreWhitespace ) );
+ registerExchangeLocation( "Japanese/IsIgnoreProlongedSoundMark",TA( m_bIsIgnoreProlongedSoundMark ) );
+ registerExchangeLocation( "Japanese/IsIgnoreMiddleDot", TA( m_bIsIgnoreMiddleDot ) );
+
+ read( );
+ }
+
+ FmSearchConfigItem::~FmSearchConfigItem()
+ {
+ commit( );
+ }
+
+ void FmSearchConfigItem::implTranslateFromConfig( )
+ {
+ // the search-for string
+ nSearchForType = lcl_implMapAsciiValue( m_sSearchForType, lcl_getSearchForTypeValueMap() );
+
+ // the search position
+ nPosition = lcl_implMapAsciiValue( m_sSearchPosition, lcl_getSearchPositionValueMap() );
+
+ // the transliteration flags
+ nTransliterationFlags = 0;
+
+ if ( !m_bIsMatchCase ) nTransliterationFlags |= TransliterationModules_IGNORE_CASE;
+ if ( m_bIsMatchFullHalfWidthForms ) nTransliterationFlags |= TransliterationModules_IGNORE_WIDTH;
+ if ( m_bIsMatchHiraganaKatakana ) nTransliterationFlags |= TransliterationModules_IGNORE_KANA;
+ if ( m_bIsMatchContractions ) nTransliterationFlags |= TransliterationModules_ignoreSize_ja_JP;
+ if ( m_bIsMatchMinusDashCho_on ) nTransliterationFlags |= TransliterationModules_ignoreMinusSign_ja_JP;
+ if ( m_bIsMatchRepeatCharMarks ) nTransliterationFlags |= TransliterationModules_ignoreIterationMark_ja_JP;
+ if ( m_bIsMatchVariantFormKanji ) nTransliterationFlags |= TransliterationModules_ignoreTraditionalKanji_ja_JP;
+ if ( m_bIsMatchOldKanaForms ) nTransliterationFlags |= TransliterationModules_ignoreTraditionalKana_ja_JP;
+ if ( m_bIsMatch_DiZi_DuZu ) nTransliterationFlags |= TransliterationModules_ignoreZiZu_ja_JP;
+ if ( m_bIsMatch_BaVa_HaFa ) nTransliterationFlags |= TransliterationModules_ignoreBaFa_ja_JP;
+ if ( m_bIsMatch_TsiThiChi_DhiZi ) nTransliterationFlags |= TransliterationModules_ignoreTiJi_ja_JP;
+ if ( m_bIsMatch_HyuIyu_ByuVyu ) nTransliterationFlags |= TransliterationModules_ignoreHyuByu_ja_JP;
+ if ( m_bIsMatch_SeShe_ZeJe ) nTransliterationFlags |= TransliterationModules_ignoreSeZe_ja_JP;
+ if ( m_bIsMatch_IaIya ) nTransliterationFlags |= TransliterationModules_ignoreIandEfollowedByYa_ja_JP;
+ if ( m_bIsMatch_KiKu ) nTransliterationFlags |= TransliterationModules_ignoreKiKuFollowedBySa_ja_JP;
+
+ if ( m_bIsIgnorePunctuation ) nTransliterationFlags |= TransliterationModules_ignoreSeparator_ja_JP;
+ if ( m_bIsIgnoreWhitespace ) nTransliterationFlags |= TransliterationModules_ignoreSpace_ja_JP;
+ if ( m_bIsIgnoreProlongedSoundMark ) nTransliterationFlags |= TransliterationModules_ignoreProlongedSoundMark_ja_JP;
+ if ( m_bIsIgnoreMiddleDot ) nTransliterationFlags |= TransliterationModules_ignoreMiddleDot_ja_JP;
+ }
+
+ void FmSearchConfigItem::implTranslateToConfig( )
+ {
+ // the search-for string
+ m_sSearchForType = ::rtl::OUString::createFromAscii( lcl_implMapIntValue( nSearchForType, lcl_getSearchForTypeValueMap() ) );
+
+ // the search position
+ m_sSearchPosition = ::rtl::OUString::createFromAscii( lcl_implMapIntValue( nPosition, lcl_getSearchPositionValueMap() ) );
+
+ // the transliteration flags
+
+ m_bIsMatchCase = ( 0 == ( nTransliterationFlags & TransliterationModules_IGNORE_CASE ) );
+ m_bIsMatchFullHalfWidthForms = ( 0 != ( nTransliterationFlags & TransliterationModules_IGNORE_WIDTH ) );
+ m_bIsMatchHiraganaKatakana = ( 0 != ( nTransliterationFlags & TransliterationModules_IGNORE_KANA ) );
+ m_bIsMatchContractions = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreSize_ja_JP ) );
+ m_bIsMatchMinusDashCho_on = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreMinusSign_ja_JP ) );
+ m_bIsMatchRepeatCharMarks = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreIterationMark_ja_JP ) );
+ m_bIsMatchVariantFormKanji = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreTraditionalKanji_ja_JP ) );
+ m_bIsMatchOldKanaForms = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreTraditionalKana_ja_JP ) );
+ m_bIsMatch_DiZi_DuZu = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreZiZu_ja_JP ) );
+ m_bIsMatch_BaVa_HaFa = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreBaFa_ja_JP ) );
+ m_bIsMatch_TsiThiChi_DhiZi = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreTiJi_ja_JP ) );
+ m_bIsMatch_HyuIyu_ByuVyu = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreHyuByu_ja_JP ) );
+ m_bIsMatch_SeShe_ZeJe = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreSeZe_ja_JP ) );
+ m_bIsMatch_IaIya = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreIandEfollowedByYa_ja_JP ) );
+ m_bIsMatch_KiKu = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreKiKuFollowedBySa_ja_JP ) );
+
+ m_bIsIgnorePunctuation = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreSeparator_ja_JP ) );
+ m_bIsIgnoreWhitespace = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreSpace_ja_JP ) );
+ m_bIsIgnoreProlongedSoundMark = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreProlongedSoundMark_ja_JP ) );
+ m_bIsIgnoreMiddleDot = ( 0 != ( nTransliterationFlags & TransliterationModules_ignoreMiddleDot_ja_JP ) );
+ }
+
+ const FmSearchParams& FmSearchConfigItem::getParams() const
+ {
+ // ensure that the properties which are not stored directly are up-to-date
+ const_cast< FmSearchConfigItem* >( this )->implTranslateFromConfig( );
+
+ // and return our FmSearchParams part
+ return *this;
+ }
+
+ void FmSearchConfigItem::setParams( const FmSearchParams& _rParams )
+ {
+ // copy the FmSearchParams part
+ *static_cast< FmSearchParams* >( this ) = _rParams;
+
+ // translate the settings not represented by a direct config value
+ implTranslateToConfig();
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmsrcimp.cxx b/svx/source/form/fmsrcimp.cxx
new file mode 100644
index 000000000000..18c045e32b27
--- /dev/null
+++ b/svx/source/form/fmsrcimp.cxx
@@ -0,0 +1,1300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmresids.hrc"
+#include "svx/fmtools.hxx"
+#include "fmsrccfg.hxx"
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/wldcrd.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/shl.hxx>
+#include <svx/dialmgr.hxx>
+#include <cppuhelper/servicefactory.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/textsearch.hxx>
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchAlgorithms.hpp>
+#include <com/sun/star/util/SearchResult.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormats.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include "fmprop.hrc"
+#include "fmservs.hxx"
+#include "fmsrcimp.hxx"
+#include <svx/fmsearch.hxx>
+
+#include <comphelper/numbers.hxx>
+#include <unotools/syslocale.hxx>
+
+#define EQUAL_BOOKMARKS(a, b) a == b
+
+#define IFACECAST(c) ((const Reference< XInterface >&)c)
+ // SUN C52 has some ambiguities without this cast ....
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::beans;
+using namespace ::svxform;
+
+// ***************************************************************************************************
+
+// ***************************************************************************************************
+
+SV_IMPL_OBJARR(SvInt32Array, sal_Int32);
+
+//========================================================================
+// = FmSearchThread
+//------------------------------------------------------------------------
+void FmSearchThread::run()
+{
+ m_pEngine->SearchNextImpl();
+};
+
+//------------------------------------------------------------------------
+void FmSearchThread::onTerminated()
+{
+ if (m_aTerminationHdl.IsSet())
+ m_aTerminationHdl.Call(this);
+ delete this;
+}
+
+//========================================================================
+// = FmRecordCountListener
+
+// SMART_UNO_IMPLEMENTATION(FmRecordCountListener, UsrObject);
+
+DBG_NAME(FmRecordCountListener);
+//------------------------------------------------------------------------
+FmRecordCountListener::FmRecordCountListener(const Reference< ::com::sun::star::sdbc::XResultSet > & dbcCursor)
+{
+ DBG_CTOR(FmRecordCountListener,NULL);
+
+ m_xListening = Reference< ::com::sun::star::beans::XPropertySet > (dbcCursor, UNO_QUERY);
+ if (!m_xListening.is())
+ return;
+
+ if (::comphelper::getBOOL(m_xListening->getPropertyValue(FM_PROP_ROWCOUNTFINAL)))
+ {
+ m_xListening = NULL;
+ // there's nothing to do as the record count is already known
+ return;
+ }
+
+ m_xListening->addPropertyChangeListener(FM_PROP_ROWCOUNT, (::com::sun::star::beans::XPropertyChangeListener*)this);
+}
+
+//------------------------------------------------------------------------
+Link FmRecordCountListener::SetPropChangeHandler(const Link& lnk)
+{
+ Link lnkReturn = m_lnkWhoWantsToKnow;
+ m_lnkWhoWantsToKnow = lnk;
+
+ if (m_xListening.is())
+ NotifyCurrentCount();
+
+ return lnkReturn;
+}
+
+//------------------------------------------------------------------------
+FmRecordCountListener::~FmRecordCountListener()
+{
+
+ DBG_DTOR(FmRecordCountListener,NULL);
+}
+
+//------------------------------------------------------------------------
+void FmRecordCountListener::DisConnect()
+{
+ if(m_xListening.is())
+ m_xListening->removePropertyChangeListener(FM_PROP_ROWCOUNT, (::com::sun::star::beans::XPropertyChangeListener*)this);
+ m_xListening = NULL;
+}
+
+//------------------------------------------------------------------------
+void SAL_CALL FmRecordCountListener::disposing(const ::com::sun::star::lang::EventObject& /*Source*/) throw( RuntimeException )
+{
+ DBG_ASSERT(m_xListening.is(), "FmRecordCountListener::disposing should never have been called without a propset !");
+ DisConnect();
+}
+
+//------------------------------------------------------------------------
+void FmRecordCountListener::NotifyCurrentCount()
+{
+ if (m_lnkWhoWantsToKnow.IsSet())
+ {
+ DBG_ASSERT(m_xListening.is(), "FmRecordCountListener::NotifyCurrentCount : I have no propset ... !?");
+ void* pTheCount = (void*)::comphelper::getINT32(m_xListening->getPropertyValue(FM_PROP_ROWCOUNT));
+ m_lnkWhoWantsToKnow.Call(pTheCount);
+ }
+}
+
+//------------------------------------------------------------------------
+void FmRecordCountListener::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& /*evt*/) throw(::com::sun::star::uno::RuntimeException)
+{
+ NotifyCurrentCount();
+}
+
+//========================================================================
+// FmSearchEngine - local classes
+//------------------------------------------------------------------------
+SimpleTextWrapper::SimpleTextWrapper(const Reference< ::com::sun::star::awt::XTextComponent > & _xText)
+ :ControlTextWrapper(_xText.get())
+ ,m_xText(_xText)
+{
+ DBG_ASSERT(m_xText.is(), "FmSearchEngine::SimpleTextWrapper::SimpleTextWrapper : invalid argument !");
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString SimpleTextWrapper::getCurrentText() const
+{
+ return m_xText->getText();
+}
+
+//------------------------------------------------------------------------
+ListBoxWrapper::ListBoxWrapper(const Reference< ::com::sun::star::awt::XListBox > & _xBox)
+ :ControlTextWrapper(_xBox.get())
+ ,m_xBox(_xBox)
+{
+ DBG_ASSERT(m_xBox.is(), "FmSearchEngine::ListBoxWrapper::ListBoxWrapper : invalid argument !");
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString ListBoxWrapper::getCurrentText() const
+{
+ return m_xBox->getSelectedItem();
+}
+
+//------------------------------------------------------------------------
+CheckBoxWrapper::CheckBoxWrapper(const Reference< ::com::sun::star::awt::XCheckBox > & _xBox)
+ :ControlTextWrapper(_xBox.get())
+ ,m_xBox(_xBox)
+{
+ DBG_ASSERT(m_xBox.is(), "FmSearchEngine::CheckBoxWrapper::CheckBoxWrapper : invalid argument !");
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString CheckBoxWrapper::getCurrentText() const
+{
+ switch ((TriState)m_xBox->getState())
+ {
+ case STATE_NOCHECK: return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"));
+ case STATE_CHECK: return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("1"));
+ default: break;
+ }
+ return rtl::OUString();
+}
+
+//========================================================================
+// = FmSearchEngine
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::MoveCursor()
+{
+ sal_Bool bSuccess = sal_True;
+ try
+ {
+ if (m_bForward)
+ if (m_xSearchCursor.isLast())
+ m_xSearchCursor.first();
+ else
+ m_xSearchCursor.next();
+ else
+ if (m_xSearchCursor.isFirst())
+ {
+ FmRecordCountListener* prclListener = new FmRecordCountListener(m_xSearchCursor);
+ prclListener->acquire();
+ prclListener->SetPropChangeHandler(LINK(this, FmSearchEngine, OnNewRecordCount));
+
+ m_xSearchCursor.last();
+
+ prclListener->DisConnect();
+ prclListener->release();
+ }
+ else
+ m_xSearchCursor.previous();
+ }
+ catch(::com::sun::star::sdbc::SQLException const& e)
+ {
+#if OSL_DEBUG_LEVEL > 0
+ String sDebugMessage;
+ sDebugMessage.AssignAscii("FmSearchEngine::MoveCursor : catched a DatabaseException (");
+ sDebugMessage += (const sal_Unicode*)e.SQLState;
+ sDebugMessage.AppendAscii(") !");
+ DBG_ERROR(ByteString(sDebugMessage, RTL_TEXTENCODING_ASCII_US).GetBuffer());
+#endif
+ bSuccess = sal_False;
+ }
+ catch(Exception const& e)
+ {
+#if OSL_DEBUG_LEVEL > 0
+ UniString sDebugMessage;
+ sDebugMessage.AssignAscii("FmSearchEngine::MoveCursor : catched an Exception (");
+ sDebugMessage += (const sal_Unicode*)e.Message;
+ sDebugMessage.AppendAscii(") !");
+ DBG_ERROR(ByteString(sDebugMessage, RTL_TEXTENCODING_ASCII_US).GetBuffer());
+#endif
+ bSuccess = sal_False;
+ }
+ catch(...)
+ {
+ DBG_ERROR("FmSearchEngine::MoveCursor : catched an unknown Exception !");
+ bSuccess = sal_False;
+ }
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::MoveField(sal_Int32& nPos, FieldCollectionIterator& iter, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd)
+{
+ sal_Bool bSuccess(sal_True);
+ if (m_bForward)
+ {
+ ++iter;
+ ++nPos;
+ if (iter == iterEnd)
+ {
+ bSuccess = MoveCursor();
+ iter = iterBegin;
+ nPos = 0;
+ }
+ } else
+ {
+ if (iter == iterBegin)
+ {
+ bSuccess = MoveCursor();
+ iter = iterEnd;
+ nPos = iter-iterBegin;
+ }
+ --iter;
+ --nPos;
+ }
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::BuildAndInsertFieldInfo(const Reference< ::com::sun::star::container::XIndexAccess > & xAllFields, sal_Int32 nField)
+{
+ DBG_ASSERT( xAllFields.is() && ( nField >= 0 ) && ( nField < xAllFields->getCount() ),
+ "FmSearchEngine::BuildAndInsertFieldInfo: invalid field descriptor!" );
+
+ // das Feld selber
+ Reference< XInterface > xCurrentField;
+ xAllFields->getByIndex(nField) >>= xCurrentField;
+
+ // von dem weiss ich jetzt, dass es den DatabaseRecord-Service unterstuetzt (hoffe ich)
+ // fuer den FormatKey und den Typ brauche ich das PropertySet
+ Reference< ::com::sun::star::beans::XPropertySet > xProperties(xCurrentField, UNO_QUERY);
+
+ // die FieldInfo dazu aufbauen
+ FieldInfo fiCurrent;
+ fiCurrent.xContents = Reference< ::com::sun::star::sdb::XColumn > (xCurrentField, UNO_QUERY);
+ fiCurrent.nFormatKey = ::comphelper::getINT32(xProperties->getPropertyValue(FM_PROP_FORMATKEY));
+ fiCurrent.bDoubleHandling = sal_False;
+ if (m_xFormatSupplier.is())
+ {
+ Reference< ::com::sun::star::util::XNumberFormats > xNumberFormats(m_xFormatSupplier->getNumberFormats());
+
+ sal_Int16 nFormatType = ::comphelper::getNumberFormatType(xNumberFormats, fiCurrent.nFormatKey) & ~((sal_Int16)::com::sun::star::util::NumberFormat::DEFINED);
+ fiCurrent.bDoubleHandling = (nFormatType != ::com::sun::star::util::NumberFormat::TEXT);
+ }
+
+ // und merken
+ m_arrUsedFields.insert(m_arrUsedFields.end(), fiCurrent);
+
+}
+//------------------------------------------------------------------------
+::rtl::OUString FmSearchEngine::FormatField(const FieldInfo& rField)
+{
+ DBG_ASSERT(!m_bUsingTextComponents, "FmSearchEngine::FormatField : im UsingTextComponents-Mode bitte FormatField(sal_Int32) benutzen !");
+
+ if (!m_xFormatter.is())
+ return ::rtl::OUString();
+ // sonst werden Datumsflder zum Beispiel zu irgendeinem Default-Wert formatiert
+
+ ::rtl::OUString sReturn;
+ try
+ {
+ if (rField.bDoubleHandling)
+ {
+ double fValue = rField.xContents->getDouble();
+ if (!rField.xContents->wasNull())
+ sReturn = m_xFormatter->convertNumberToString(rField.nFormatKey, fValue);
+ }
+ else
+ {
+ ::rtl::OUString sValue = rField.xContents->getString();
+ if (!rField.xContents->wasNull())
+ sReturn = m_xFormatter->formatString(rField.nFormatKey, sValue);
+ }
+ }
+ catch(...)
+ {
+ }
+
+
+ return sReturn;
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString FmSearchEngine::FormatField(sal_Int32 nWhich)
+{
+ if (m_bUsingTextComponents)
+ {
+ DBG_ASSERT((sal_uInt32)nWhich < m_aControlTexts.size(), "FmSearchEngine::FormatField(sal_Int32) : invalid position !");
+ DBG_ASSERT(m_aControlTexts[nWhich] != NULL, "FmSearchEngine::FormatField(sal_Int32) : invalid object in array !");
+ DBG_ASSERT(m_aControlTexts[nWhich]->getControl().is(), "FmSearchEngine::FormatField : invalid control !");
+
+ if (m_nCurrentFieldIndex != -1)
+ {
+ DBG_ASSERT((nWhich == 0) || (nWhich == m_nCurrentFieldIndex), "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig");
+ // analoge Situation wie unten
+ nWhich = m_nCurrentFieldIndex;
+ }
+
+ DBG_ASSERT((nWhich >= 0) && ((sal_uInt32)nWhich < m_aControlTexts.size()),
+ "FmSearchEngine::FormatField : invalid argument nWhich !");
+ return m_aControlTexts[m_nCurrentFieldIndex == -1 ? nWhich : m_nCurrentFieldIndex]->getCurrentText();
+ }
+ else
+ {
+ if (m_nCurrentFieldIndex != -1)
+ {
+ DBG_ASSERT((nWhich == 0) || (nWhich == m_nCurrentFieldIndex), "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig");
+ // ich bin im single-field-modus, da ist auch die richtige Feld-Nummer erlaubt, obwohl dann der richtige ::com::sun::star::sdbcx::Index
+ // fuer meinen Array-Zugriff natuerlich 0 ist
+ nWhich = 0;
+ }
+
+ DBG_ASSERT((nWhich>=0) && (nWhich < (m_arrUsedFields.end() - m_arrUsedFields.begin())),
+ "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig");
+ return FormatField(m_arrUsedFields[nWhich]);
+ }
+}
+
+//------------------------------------------------------------------------
+FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchSpecial(sal_Bool _bSearchForNull, sal_Int32& nFieldPos,
+ FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd)
+{
+ // die Startposition merken
+ Any aStartMark;
+ try { aStartMark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+ FieldCollectionIterator iterInitialField = iterFieldLoop;
+
+ // --------------------------------------------------------------
+ sal_Bool bFound(sal_False);
+ sal_Bool bMovedAround(sal_False);
+ do
+ {
+ if (m_eMode == SM_ALLOWSCHEDULE)
+ {
+ Application::Reschedule();
+ Application::Reschedule();
+ // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
+ // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
+ // or anything like that. So within each loop we create one user event and handle one user event (and no
+ // paintings and these), so the office seems to be frozen while searching.
+ // FS - 70226 - 02.12.99
+ }
+
+ // der aktuell zu vergleichende Inhalt
+ iterFieldLoop->xContents->getString(); // needed for wasNull
+ bFound = _bSearchForNull == iterFieldLoop->xContents->wasNull();
+ if (bFound)
+ break;
+
+ // naechstes Feld (implizit naechster Datensatz, wenn noetig)
+ if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
+ { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau
+ // das selbe bestimmt wieder schief geht, also Abbruch
+ // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht :
+ try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
+ m_iterPreviousLocField = iterFieldLoop;
+ // und wech
+ return SR_ERROR;
+ }
+
+ Any aCurrentBookmark;
+ try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+
+ bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
+
+ if (nFieldPos == 0)
+ // das heisst, ich habe mich auf einen neuen Datensatz bewegt
+ PropagateProgress(bMovedAround);
+ // if we moved to the starting position we don't have to propagate an 'overflow' message
+ // FS - 07.12.99 - 68530
+
+ // abbrechen gefordert ?
+ if (CancelRequested())
+ return SR_CANCELED;
+
+ } while (!bMovedAround);
+
+ return bFound ? SR_FOUND : SR_NOTFOUND;
+}
+
+//------------------------------------------------------------------------
+FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchWildcard(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos,
+ FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd)
+{
+ // die Startposition merken
+ Any aStartMark;
+ try { aStartMark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+ FieldCollectionIterator iterInitialField = iterFieldLoop;
+
+ WildCard aSearchExpression(strExpression);
+
+ // --------------------------------------------------------------
+ sal_Bool bFound(sal_False);
+ sal_Bool bMovedAround(sal_False);
+ do
+ {
+ if (m_eMode == SM_ALLOWSCHEDULE)
+ {
+ Application::Reschedule();
+ Application::Reschedule();
+ // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
+ // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
+ // or anything like that. So within each loop we create one user event and hanel one user event (and no
+ // paintings and these), so the office seems to be frozen while searching.
+ // FS - 70226 - 02.12.99
+ }
+
+ // der aktuell zu vergleichende Inhalt
+ ::rtl::OUString sCurrentCheck;
+ if (m_bFormatter)
+ sCurrentCheck = FormatField(nFieldPos);
+ else
+ sCurrentCheck = iterFieldLoop->xContents->getString();
+
+ if (!GetCaseSensitive())
+ // norm the string
+ m_aCharacterClassficator.toLower_rtl(sCurrentCheck);
+
+ // jetzt ist der Test einfach ...
+ bFound = aSearchExpression.Matches(sCurrentCheck);
+
+ if (bFound)
+ break;
+
+ // naechstes Feld (implizit naechster Datensatz, wenn noetig)
+ if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
+ { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau
+ // das selbe bestimmt wieder schief geht, also Abbruch
+ // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht :
+ try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
+ m_iterPreviousLocField = iterFieldLoop;
+ // und wech
+ return SR_ERROR;
+ }
+
+ Any aCurrentBookmark;
+ try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+
+ bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
+
+ if (nFieldPos == 0)
+ // das heisst, ich habe mich auf einen neuen Datensatz bewegt
+ PropagateProgress(bMovedAround);
+ // if we moved to the starting position we don't have to propagate an 'overflow' message
+ // FS - 07.12.99 - 68530
+
+ // abbrechen gefordert ?
+ if (CancelRequested())
+ return SR_CANCELED;
+
+ } while (!bMovedAround);
+
+ return bFound ? SR_FOUND : SR_NOTFOUND;
+}
+
+//------------------------------------------------------------------------
+FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchRegularApprox(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos,
+ FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd)
+{
+ DBG_ASSERT(m_bLevenshtein || m_bRegular,
+ "FmSearchEngine::SearchRegularApprox : ungueltiger Suchmodus !");
+ DBG_ASSERT(!m_bLevenshtein || !m_bRegular,
+ "FmSearchEngine::SearchRegularApprox : kann nicht nach regulaeren Ausdruecken und nach Aehnlichkeiten gleichzeitig suchen !");
+
+ // Startposition merken
+ Any aStartMark;
+ try { aStartMark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+ FieldCollectionIterator iterInitialField = iterFieldLoop;
+
+ // Parameter sammeln
+ SearchOptions aParam;
+ aParam.algorithmType = m_bRegular ? SearchAlgorithms_REGEXP : SearchAlgorithms_APPROXIMATE;
+ aParam.searchFlag = 0;
+ aParam.transliterateFlags = GetTransliterationFlags();
+ if ( !GetTransliteration() )
+ { // if transliteration is not enabled, the only flags which matter are IGNORE_CASE and IGNORE_WIDTH
+ aParam.transliterateFlags &= TransliterationModules_IGNORE_CASE | TransliterationModules_IGNORE_WIDTH;
+ }
+ if (m_bLevenshtein)
+ {
+ if (m_bLevRelaxed)
+ aParam.searchFlag |= SearchFlags::LEV_RELAXED;
+ aParam.changedChars = m_nLevOther;
+ aParam.deletedChars = m_nLevShorter;
+ aParam.insertedChars = m_nLevLonger;
+ }
+ aParam.searchString = strExpression;
+ aParam.Locale = SvtSysLocale().GetLocaleData().getLocale();
+ ::utl::TextSearch aLocalEngine(aParam);
+
+ // --------------------------------------------------------------
+ bool bFound = false;
+ sal_Bool bMovedAround(sal_False);
+ do
+ {
+ if (m_eMode == SM_ALLOWSCHEDULE)
+ {
+ Application::Reschedule();
+ Application::Reschedule();
+ // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
+ // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
+ // or anything like that. So within each loop we create one user event and handle one user event (and no
+ // paintings and these), so the office seems to be frozen while searching.
+ // FS - 70226 - 02.12.99
+ }
+
+ // der aktuell zu vergleichende Inhalt
+ ::rtl::OUString sCurrentCheck;
+ if (m_bFormatter)
+ sCurrentCheck = FormatField(nFieldPos);
+ else
+ sCurrentCheck = iterFieldLoop->xContents->getString();
+
+ // (don't care about case here, this is done by the TextSearch object, 'cause we passed our case parameter to it)
+
+ xub_StrLen nStart = 0, nEnd = (xub_StrLen)sCurrentCheck.getLength();
+ bFound = aLocalEngine.SearchFrwrd(sCurrentCheck, &nStart, &nEnd);
+ // das heisst hier 'forward' aber das bezieht sich nur auf die Suche innerhalb von sCurrentCheck, hat also mit
+ // der Richtung meines Datensatz-Durchwanderns nix zu tun (darum kuemmert sich MoveField)
+
+ // checken, ob die Position stimmt
+ if (bFound)
+ {
+ switch (m_nPosition)
+ {
+ case MATCHING_WHOLETEXT :
+ if (nEnd != sCurrentCheck.getLength())
+ {
+ bFound = false;
+ break;
+ }
+ // laeuft in den naechsten Case rein !
+ case MATCHING_BEGINNING :
+ if (nStart != 0)
+ bFound = false;
+ break;
+ case MATCHING_END :
+ if (nEnd != sCurrentCheck.getLength())
+ bFound = false;
+ break;
+ }
+ }
+
+ if (bFound) // immer noch ?
+ break;
+
+ // naechstes Feld (implizit naechster Datensatz, wenn noetig)
+ if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
+ { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau
+ // das selbe bestimmt wieder schief geht, also Abbruch (ohne Fehlermeldung, von der erwarte ich, dass sie im Move
+ // angezeigt wurde)
+ // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht :
+ try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
+ m_iterPreviousLocField = iterFieldLoop;
+ // und wech
+ return SR_ERROR;
+ }
+
+ Any aCurrentBookmark;
+ try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; }
+ bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
+
+ if (nFieldPos == 0)
+ // das heisst, ich habe mich auf einen neuen Datensatz bewegt
+ PropagateProgress(bMovedAround);
+ // if we moved to the starting position we don't have to propagate an 'overflow' message
+ // FS - 07.12.99 - 68530
+
+ // abbrechen gefordert ?
+ if (CancelRequested())
+ return SR_CANCELED;
+
+ } while (!bMovedAround);
+
+ return bFound ? SR_FOUND : SR_NOTFOUND;
+}
+
+
+DBG_NAME(FmSearchEngine);
+//------------------------------------------------------------------------
+FmSearchEngine::FmSearchEngine(const Reference< XMultiServiceFactory >& _rxORB,
+ const Reference< XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields,
+ const Reference< XNumberFormatsSupplier > & xFormatSupplier, FMSEARCH_MODE eMode)
+
+ :m_xSearchCursor(xCursor)
+ ,m_xFormatSupplier(xFormatSupplier)
+ ,m_aCharacterClassficator( _rxORB, SvtSysLocale().GetLocaleData().getLocale() )
+ ,m_aStringCompare( _rxORB )
+ ,m_nCurrentFieldIndex(-2) // -1 hat schon eine Bedeutung, also nehme ich -2 fuer 'ungueltig'
+ ,m_bUsingTextComponents(sal_False)
+ ,m_eSearchForType(SEARCHFOR_STRING)
+ ,m_srResult(SR_FOUND)
+ ,m_bSearchingCurrently(sal_False)
+ ,m_bCancelAsynchRequest(sal_False)
+ ,m_eMode(eMode)
+ ,m_bFormatter(sal_False)
+ ,m_bForward(sal_False)
+ ,m_bWildcard(sal_False)
+ ,m_bRegular(sal_False)
+ ,m_bLevenshtein(sal_False)
+ ,m_bTransliteration(sal_False)
+ ,m_bLevRelaxed(sal_False)
+ ,m_nLevOther(0)
+ ,m_nLevShorter(0)
+ ,m_nLevLonger(0)
+ ,m_nPosition(MATCHING_ANYWHERE)
+ ,m_nTransliterationFlags(0)
+{
+ DBG_CTOR(FmSearchEngine,NULL);
+
+ m_xFormatter = Reference< ::com::sun::star::util::XNumberFormatter > (::comphelper::getProcessServiceFactory()
+ ->createInstance(FM_NUMBER_FORMATTER), UNO_QUERY);
+ if (m_xFormatter.is())
+ m_xFormatter->attachNumberFormatsSupplier(m_xFormatSupplier);
+
+ Init(sVisibleFields);
+}
+
+//------------------------------------------------------------------------
+FmSearchEngine::FmSearchEngine(const Reference< XMultiServiceFactory >& _rxORB,
+ const Reference< XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields,
+ const InterfaceArray& arrFields, FMSEARCH_MODE eMode)
+ :m_xSearchCursor(xCursor)
+ ,m_aCharacterClassficator( _rxORB, SvtSysLocale().GetLocaleData().getLocale() )
+ ,m_aStringCompare( _rxORB )
+ ,m_nCurrentFieldIndex(-2) // -1 hat schon eine Bedeutung, also nehme ich -2 fuer 'ungueltig'
+ ,m_bUsingTextComponents(sal_True)
+ ,m_xOriginalIterator(xCursor)
+ ,m_xClonedIterator(m_xOriginalIterator, sal_True)
+ ,m_eSearchForType(SEARCHFOR_STRING)
+ ,m_srResult(SR_FOUND)
+ ,m_bSearchingCurrently(sal_False)
+ ,m_bCancelAsynchRequest(sal_False)
+ ,m_eMode(eMode)
+ ,m_bFormatter(sal_True) // das muss konsistent sein mit m_xSearchCursor, der i.A. == m_xOriginalIterator ist
+ ,m_bForward(sal_False)
+ ,m_bWildcard(sal_False)
+ ,m_bRegular(sal_False)
+ ,m_bLevenshtein(sal_False)
+ ,m_bTransliteration(sal_False)
+ ,m_bLevRelaxed(sal_False)
+ ,m_nLevOther(0)
+ ,m_nLevShorter(0)
+ ,m_nLevLonger(0)
+ ,m_nPosition(MATCHING_ANYWHERE)
+ ,m_nTransliterationFlags(0)
+{
+ DBG_CTOR(FmSearchEngine,NULL);
+
+ fillControlTexts(arrFields);
+ Init(sVisibleFields);
+}
+
+//------------------------------------------------------------------------
+FmSearchEngine::~FmSearchEngine()
+{
+ clearControlTexts();
+
+ DBG_DTOR(FmSearchEngine,NULL);
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SetIgnoreWidthCJK(sal_Bool bSet)
+{
+ if (bSet)
+ m_nTransliterationFlags |= TransliterationModules_IGNORE_WIDTH;
+ else
+ m_nTransliterationFlags &= ~TransliterationModules_IGNORE_WIDTH;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::GetIgnoreWidthCJK() const
+{
+ return 0 != (m_nTransliterationFlags & TransliterationModules_IGNORE_WIDTH);
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SetCaseSensitive(sal_Bool bSet)
+{
+ if (bSet)
+ m_nTransliterationFlags &= ~TransliterationModules_IGNORE_CASE;
+ else
+ m_nTransliterationFlags |= TransliterationModules_IGNORE_CASE;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::GetCaseSensitive() const
+{
+ return 0 == (m_nTransliterationFlags & TransliterationModules_IGNORE_CASE);
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::clearControlTexts()
+{
+ for ( ControlTextSuppliersIterator aIter = m_aControlTexts.begin();
+ aIter < m_aControlTexts.end();
+ ++aIter
+ )
+ {
+ delete *aIter;
+ }
+ m_aControlTexts.clear();
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::fillControlTexts(const InterfaceArray& arrFields)
+{
+ clearControlTexts();
+ Reference< XInterface > xCurrent;
+ for (sal_uInt32 i=0; i<arrFields.size(); ++i)
+ {
+ xCurrent = arrFields.at(i);
+ DBG_ASSERT(xCurrent.is(), "FmSearchEngine::fillControlTexts : invalid field interface !");
+ // check which type of control this is
+ Reference< ::com::sun::star::awt::XTextComponent > xAsText(xCurrent, UNO_QUERY);
+ if (xAsText.is())
+ {
+ m_aControlTexts.insert(m_aControlTexts.end(), new SimpleTextWrapper(xAsText));
+ continue;
+ }
+
+ Reference< ::com::sun::star::awt::XListBox > xAsListBox(xCurrent, UNO_QUERY);
+ if (xAsListBox.is())
+ {
+ m_aControlTexts.insert(m_aControlTexts.end(), new ListBoxWrapper(xAsListBox));
+ continue;
+ }
+
+ Reference< ::com::sun::star::awt::XCheckBox > xAsCheckBox(xCurrent, UNO_QUERY);
+ DBG_ASSERT(xAsCheckBox.is(), "FmSearchEngine::fillControlTexts : invalid field interface (no supported type) !");
+ // we don't have any more options ...
+ m_aControlTexts.insert(m_aControlTexts.end(), new CheckBoxWrapper(xAsCheckBox));
+ }
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::Init(const ::rtl::OUString& sVisibleFields)
+{
+ // analyze the fields
+ // additionally, create the mapping: because the list of used columns can be shorter than the list
+ // of columns of the cursor, we need a mapping: "used column numer n" -> "cursor column m"
+ m_arrFieldMapping.Remove(0, m_arrFieldMapping.Count());
+
+ // important: The case of the columns does not need to be exact - for instance:
+ // - a user created a form which works on a table, for which the driver returns a column name "COLUMN"
+ // - the driver itself works case-insensitve with column names
+ // - a control in the form is bound to "column" - not the different case
+ // In such a scenario, the form and the field would work okay, but we here need to case for the different case
+ // explicitly
+ // 2003-01-09 - #i8755# - fs@openoffice.org
+
+ // so first of all, check if the database handles identifiers case sensitive
+ Reference< XConnection > xConn;
+ Reference< XDatabaseMetaData > xMeta;
+ Reference< XPropertySet > xCursorProps( IFACECAST( m_xSearchCursor ), UNO_QUERY );
+ if ( xCursorProps.is() )
+ {
+ try
+ {
+ xCursorProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ) >>= xConn;
+ }
+ catch( Exception& ) { /* silent this - will be asserted below */ }
+ }
+ if ( xConn.is() )
+ xMeta = xConn->getMetaData();
+ OSL_ENSURE( xMeta.is(), "FmSearchEngine::Init: very strange cursor (could not derive connection meta data from it)!" );
+
+ sal_Bool bCaseSensitiveIdentifiers = sal_True; // assume case sensivity
+ if ( xMeta.is() )
+ bCaseSensitiveIdentifiers = xMeta->supportsMixedCaseQuotedIdentifiers();
+
+ // now that we have this information, we need a collator which is able to case (in)sentively compare strings
+ m_aStringCompare.loadDefaultCollator( SvtSysLocale().GetLocaleData().getLocale(),
+ bCaseSensitiveIdentifiers ? 0 : ::com::sun::star::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE );
+
+ try
+ {
+ // der Cursor kann mir einen Record (als PropertySet) liefern, dieser unterstuetzt den DatabaseRecord-Service
+ Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY);
+ DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::Init : invalid cursor (no columns supplier) !");
+ Reference< ::com::sun::star::container::XNameAccess > xAllFieldNames = xSupplyCols->getColumns();
+ Sequence< ::rtl::OUString > seqFieldNames = xAllFieldNames->getElementNames();
+ ::rtl::OUString* pFieldNames = seqFieldNames.getArray();
+
+
+ ::rtl::OUString sCurrentField;
+ UniString sVis(sVisibleFields.getStr());
+ xub_StrLen nLen = sVis.GetTokenCount();
+ for (xub_StrLen i=0; i<nLen; ++i)
+ {
+ sCurrentField = sVis.GetToken(i);
+
+ // in der Feld-Sammlung suchen
+ sal_Int32 nFoundIndex = -1;
+ for (sal_Int32 j=0; j<seqFieldNames.getLength(); ++j, ++pFieldNames)
+ {
+ if ( 0 == m_aStringCompare.compareString( *pFieldNames, sCurrentField ) )
+ {
+ nFoundIndex = j;
+ break;
+ }
+ }
+ // set the field selection back to the first
+ pFieldNames = seqFieldNames.getArray();;
+ DBG_ASSERT(nFoundIndex != -1, "FmSearchEngine::Init : Es wurden ungueltige Feldnamen angegeben !");
+ m_arrFieldMapping.Insert(nFoundIndex, m_arrFieldMapping.Count());
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("Exception occurred!");
+ }
+
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SetFormatterUsing(sal_Bool bSet)
+{
+ if (m_bFormatter == bSet)
+ return;
+ m_bFormatter = bSet;
+
+ if (m_bUsingTextComponents)
+ {
+ // ich benutzte keinen Formatter, sondern TextComponents -> der SearchIterator muss angepasst werden
+ try
+ {
+ if (m_bFormatter)
+ {
+ DBG_ASSERT(m_xSearchCursor == m_xClonedIterator, "FmSearchEngine::SetFormatterUsing : inkonsistenter Zustand !");
+ m_xSearchCursor = m_xOriginalIterator;
+ m_xSearchCursor.moveToBookmark(m_xClonedIterator.getBookmark());
+ // damit ich mit dem neuen Iterator wirklich dort weitermache, wo ich vorher aufgehoert habe
+ }
+ else
+ {
+ DBG_ASSERT(m_xSearchCursor == m_xOriginalIterator, "FmSearchEngine::SetFormatterUsing : inkonsistenter Zustand !");
+ m_xSearchCursor = m_xClonedIterator;
+ m_xSearchCursor.moveToBookmark(m_xOriginalIterator.getBookmark());
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // ich muss die Fields neu binden, da der Textaustausch eventuell ueber diese Fields erfolgt und sich der unterliegende Cursor
+ // geaendert hat
+ RebuildUsedFields(m_nCurrentFieldIndex, sal_True);
+ }
+ else
+ InvalidatePreviousLoc();
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::PropagateProgress(sal_Bool _bDontPropagateOverflow)
+{
+ if (m_aProgressHandler.IsSet())
+ {
+ FmSearchProgress aProgress;
+ try
+ {
+ aProgress.aSearchState = FmSearchProgress::STATE_PROGRESS;
+ aProgress.nCurrentRecord = m_xSearchCursor.getRow() - 1;
+ if (m_bForward)
+ aProgress.bOverflow = !_bDontPropagateOverflow && m_xSearchCursor.isFirst();
+ else
+ aProgress.bOverflow = !_bDontPropagateOverflow && m_xSearchCursor.isLast();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ m_aProgressHandler.Call(&aProgress);
+ }
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SearchNextImpl()
+{
+ DBG_ASSERT(!(m_bWildcard && m_bRegular) && !(m_bRegular && m_bLevenshtein) && !(m_bLevenshtein && m_bWildcard),
+ "FmSearchEngine::SearchNextImpl : Suchparameter schliessen sich gegenseitig aus !");
+
+ DBG_ASSERT(m_xSearchCursor.is(), "FmSearchEngine::SearchNextImpl : habe ungueltigen Iterator !");
+
+ // die Parameter der Suche
+ ::rtl::OUString strSearchExpression(m_strSearchExpression); // brauche ich non-const
+ if (!GetCaseSensitive())
+ // norm the string
+ m_aCharacterClassficator.toLower_rtl(strSearchExpression);
+
+ if (!m_bRegular && !m_bLevenshtein)
+ { // 'normale' Suche fuehre ich auf jeden Fall ueber WildCards durch, muss aber vorher je nach Modus den ::rtl::OUString anpassen
+
+ if (!m_bWildcard)
+ { // da natuerlich in allen anderen Faellen auch * und ? im Suchstring erlaubt sind, aber nicht als WildCards zaehlen
+ // sollen, muss ich normieren
+ UniString aTmp(strSearchExpression.getStr());
+ static const UniString s_sStar = UniString::CreateFromAscii("\\*");
+ static const UniString s_sQuotation = UniString::CreateFromAscii("\\?");
+ aTmp.SearchAndReplaceAll('*', s_sStar);
+ aTmp.SearchAndReplaceAll('?', s_sQuotation);
+ strSearchExpression = aTmp;
+
+ switch (m_nPosition)
+ {
+ case MATCHING_ANYWHERE :
+ strSearchExpression = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")) + strSearchExpression
+ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*"));
+ break;
+ case MATCHING_BEGINNING :
+ strSearchExpression = strSearchExpression + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*"));
+ break;
+ case MATCHING_END :
+ strSearchExpression = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")) + strSearchExpression;
+ break;
+ case MATCHING_WHOLETEXT :
+ break;
+ default :
+ DBG_ERROR("FmSearchEngine::SearchNextImpl() : die Methoden-Listbox duerfte nur 4 Eintraege enthalten ...");
+ }
+ }
+ }
+
+ // fuer Arbeit auf Feldliste
+ FieldCollectionIterator iterBegin = m_arrUsedFields.begin();
+ FieldCollectionIterator iterEnd = m_arrUsedFields.end();
+ FieldCollectionIterator iterFieldCheck;
+
+ sal_Int32 nFieldPos;
+
+ if (HasPreviousLoc())
+ {
+ DBG_ASSERT(EQUAL_BOOKMARKS(m_aPreviousLocBookmark, m_xSearchCursor.getBookmark()),
+ "FmSearchEngine::SearchNextImpl : ungueltige Position !");
+ iterFieldCheck = m_iterPreviousLocField;
+ // im Feld nach (oder vor) der letzten Fundstelle weitermachen
+ nFieldPos = iterFieldCheck - iterBegin;
+ MoveField(nFieldPos, iterFieldCheck, iterBegin, iterEnd);
+ }
+ else
+ {
+ if (m_bForward)
+ iterFieldCheck = iterBegin;
+ else
+ {
+ iterFieldCheck = iterEnd;
+ --iterFieldCheck;
+ }
+ nFieldPos = iterFieldCheck - iterBegin;
+ }
+
+ PropagateProgress(sal_True);
+ SEARCH_RESULT srResult;
+ if (m_eSearchForType != SEARCHFOR_STRING)
+ srResult = SearchSpecial(m_eSearchForType == SEARCHFOR_NULL, nFieldPos, iterFieldCheck, iterBegin, iterEnd);
+ else if (!m_bRegular && !m_bLevenshtein)
+ srResult = SearchWildcard(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd);
+ else
+ srResult = SearchRegularApprox(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd);
+
+ m_srResult = srResult;
+
+ if (SR_ERROR == m_srResult)
+ return;
+
+ // gefunden ?
+ if (SR_FOUND == m_srResult)
+ {
+ // die Pos merken
+ try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
+ catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
+ m_iterPreviousLocField = iterFieldCheck;
+ }
+ else
+ // die "letzte Fundstelle" invalidieren
+ InvalidatePreviousLoc();
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchEngine, OnSearchTerminated, FmSearchThread*, /*pThread*/)
+{
+ if (!m_aProgressHandler.IsSet())
+ return 0L;
+
+ FmSearchProgress aProgress;
+ try
+ {
+ switch (m_srResult)
+ {
+ case SR_ERROR :
+ aProgress.aSearchState = FmSearchProgress::STATE_ERROR;
+ break;
+ case SR_FOUND :
+ aProgress.aSearchState = FmSearchProgress::STATE_SUCCESSFULL;
+ aProgress.aBookmark = m_aPreviousLocBookmark;
+ aProgress.nFieldIndex = m_iterPreviousLocField - m_arrUsedFields.begin();
+ break;
+ case SR_NOTFOUND :
+ aProgress.aSearchState = FmSearchProgress::STATE_NOTHINGFOUND;
+ aProgress.aBookmark = m_xSearchCursor.getBookmark();
+ break;
+ case SR_CANCELED :
+ aProgress.aSearchState = FmSearchProgress::STATE_CANCELED;
+ aProgress.aBookmark = m_xSearchCursor.getBookmark();
+ break;
+ }
+ aProgress.nCurrentRecord = m_xSearchCursor.getRow() - 1;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // per definitionem muss der Link Thread-sicher sein (das verlange ich einfach), so dass ich mich um so etwas hier nicht kuemmern muss
+ m_aProgressHandler.Call(&aProgress);
+
+ m_bSearchingCurrently = sal_False;
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchEngine, OnNewRecordCount, void*, pCounterAsVoid)
+{
+ if (!m_aProgressHandler.IsSet())
+ return 0L;
+
+ FmSearchProgress aProgress;
+ aProgress.nCurrentRecord = (sal_uIntPtr)pCounterAsVoid;
+ aProgress.aSearchState = FmSearchProgress::STATE_PROGRESS_COUNTING;
+ m_aProgressHandler.Call(&aProgress);
+
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::CancelRequested()
+{
+ m_aCancelAsynchAccess.acquire();
+ sal_Bool bReturn = m_bCancelAsynchRequest;
+ m_aCancelAsynchAccess.release();
+ return bReturn;
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::CancelSearch()
+{
+ m_aCancelAsynchAccess.acquire();
+ m_bCancelAsynchRequest = sal_True;
+ m_aCancelAsynchAccess.release();
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchEngine::SwitchToContext(const Reference< ::com::sun::star::sdbc::XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields, const InterfaceArray& arrFields,
+ sal_Int32 nFieldIndex)
+{
+ DBG_ASSERT(!m_bSearchingCurrently, "FmSearchEngine::SwitchToContext : please do not call while I'm searching !");
+ if (m_bSearchingCurrently)
+ return sal_False;
+
+ m_xSearchCursor = xCursor;
+ m_xOriginalIterator = xCursor;
+ m_xClonedIterator = CursorWrapper(m_xOriginalIterator, sal_True);
+ m_bUsingTextComponents = sal_True;
+
+ fillControlTexts(arrFields);
+
+ Init(sVisibleFields);
+ RebuildUsedFields(nFieldIndex, sal_True);
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::ImplStartNextSearch()
+{
+ m_bCancelAsynchRequest = sal_False;
+ m_bSearchingCurrently = sal_True;
+
+ if (m_eMode == SM_USETHREAD)
+ {
+ FmSearchThread* pSearcher = new FmSearchThread(this);
+ // der loescht sich nach Beendigung selber ...
+ pSearcher->setTerminationHandler(LINK(this, FmSearchEngine, OnSearchTerminated));
+
+ pSearcher->createSuspended();
+ pSearcher->setPriority(osl_Thread_PriorityLowest);
+ pSearcher->resume();
+ }
+ else
+ {
+ SearchNextImpl();
+ LINK(this, FmSearchEngine, OnSearchTerminated).Call(NULL);
+ }
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SearchNext(const ::rtl::OUString& strExpression)
+{
+ m_strSearchExpression = strExpression;
+ m_eSearchForType = SEARCHFOR_STRING;
+ ImplStartNextSearch();
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::SearchNextSpecial(sal_Bool _bSearchForNull)
+{
+ m_eSearchForType = _bSearchForNull ? SEARCHFOR_NULL : SEARCHFOR_NOTNULL;
+ ImplStartNextSearch();
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::StartOver(const ::rtl::OUString& strExpression)
+{
+ try
+ {
+ if (m_bForward)
+ m_xSearchCursor.first();
+ else
+ m_xSearchCursor.last();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ return;
+ }
+
+ InvalidatePreviousLoc();
+ SearchNext(strExpression);
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::StartOverSpecial(sal_Bool _bSearchForNull)
+{
+ try
+ {
+ if (m_bForward)
+ m_xSearchCursor.first();
+ else
+ m_xSearchCursor.last();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ return;
+ }
+
+ InvalidatePreviousLoc();
+ SearchNextSpecial(_bSearchForNull);
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::InvalidatePreviousLoc()
+{
+ m_aPreviousLocBookmark.setValue(0,getVoidCppuType());
+ m_iterPreviousLocField = m_arrUsedFields.end();
+}
+
+//------------------------------------------------------------------------
+void FmSearchEngine::RebuildUsedFields(sal_Int32 nFieldIndex, sal_Bool bForce)
+{
+ if (!bForce && (nFieldIndex == m_nCurrentFieldIndex))
+ return;
+ // (da ich keinen Wechsel des Iterators von aussen zulasse, heisst selber ::com::sun::star::sdbcx::Index auch immer selbe Spalte, also habe ich nix zu tun)
+
+ DBG_ASSERT((nFieldIndex >= -1) && (nFieldIndex<m_arrFieldMapping.Count()), "FmSearchEngine::RebuildUsedFields : nFieldIndex ist ungueltig !");
+ // alle Felder, die ich durchsuchen muss, einsammeln
+ m_arrUsedFields.clear();
+ if (nFieldIndex == -1)
+ {
+ Reference< ::com::sun::star::container::XIndexAccess > xFields;
+ for (sal_uInt16 i=0; i<m_arrFieldMapping.Count(); ++i)
+ {
+ Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY);
+ DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !");
+ xFields = Reference< ::com::sun::star::container::XIndexAccess > (xSupplyCols->getColumns(), UNO_QUERY);
+ BuildAndInsertFieldInfo(xFields, m_arrFieldMapping.GetObject(i));
+ }
+ }
+ else
+ {
+ Reference< ::com::sun::star::container::XIndexAccess > xFields;
+ Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY);
+ DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !");
+ xFields = Reference< ::com::sun::star::container::XIndexAccess > (xSupplyCols->getColumns(), UNO_QUERY);
+ BuildAndInsertFieldInfo(xFields, m_arrFieldMapping.GetObject((sal_uInt16)nFieldIndex));
+ }
+
+ m_nCurrentFieldIndex = nFieldIndex;
+ // und natuerlich beginne ich die naechste Suche wieder jungfraeulich
+ InvalidatePreviousLoc();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmstring.src b/svx/source/form/fmstring.src
new file mode 100644
index 000000000000..8e3df1a8cdf5
--- /dev/null
+++ b/svx/source/form/fmstring.src
@@ -0,0 +1,491 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "fmresids.hrc"
+/* Strings fuer Uebersetzung */
+String RID_ERR_CONTEXT_ADDFORM
+{
+ Text [ en-US ] = "Error while creating form";
+};
+String RID_ERR_FIELDREQUIRED
+{
+ Text [ en-US ] = "Input required in field '#'. Please enter a value.";
+};
+String RID_ERR_DUPLICATE_NAME
+{
+ Text [ en-US ] = "Entry already exists.\nPlease choose another name.";
+};
+String RID_STR_FORMS
+{
+ Text [ en-US ] = "Forms";
+};
+String RID_STR_NO_PROPERTIES
+{
+ Text [ en-US ] = "No control selected";
+};
+String RID_STR_PROPERTIES_CONTROL
+{
+ /* ### ACHTUNG: Neuer Text in Resource? Eigenschaften: : Kontrollelement Eigenschaften */
+ Text [ en-US ] = "Properties: ";
+};
+String RID_STR_PROPERTIES_FORM
+{
+ Text [ en-US ] = "Form Properties";
+};
+String RID_STR_FMEXPLORER
+{
+ Text [ en-US ] = "Form Navigator";
+};
+String RID_STR_FORM
+{
+ Text [ en-US ] = "Form";
+};
+Resource RID_RSC_TABWIN_PREFIX
+{
+ String 1
+ {
+ Text [ en-US ] = "Table";
+ };
+ String 2
+ {
+ Text [ en-US ] = "Query";
+ };
+ String 3
+ {
+ Text [ en-US ] = "SQL";
+ };
+};
+String RID_STR_FORMSHELL
+{
+ Text = "Form Shell";
+};
+String RID_STR_STDFORMNAME
+{
+ Text [ en-US ]= "Form";
+};
+String RID_STR_PROPTITLE_HIDDEN
+{
+ Text [ en-US ] = "Hidden Control";
+};
+String RID_STR_CONTROL
+{
+ Text [ en-US ] = "Control";
+};
+String RID_STR_REC_TEXT
+{
+ Text [ en-US ] = "Record";
+};
+String RID_STR_REC_FROM_TEXT
+{
+ Text [ en-US ] = "of";
+};
+String RID_STR_FIELDSELECTION
+{
+ Text [ en-US ] = "Add field:";
+};
+String RID_STR_WRITEERROR
+{
+ Text [ en-US ] = "Error writing data to database";
+};
+
+String RID_STR_SYNTAXERROR
+{
+ Text [ en-US ] = "Syntax error in query expression";
+};
+
+String RID_STR_DELETECONFIRM_RECORD
+{
+ Text [ en-US ] = "You intend to delete 1 record.";
+};
+String RID_STR_DELETECONFIRM_RECORDS
+{
+ Text [ en-US ] = "# records will be deleted.";
+};
+String RID_STR_DELETECONFIRM
+{
+ Text [ en-US ] = "If you click Yes, you won't be able to undo this operation.\nDo you want to continue anyway?";
+};
+
+String RID_ERR_NO_ELEMENT
+{
+ Text [ en-US ] = "Choose an entry from the list or enter a text corresponding to one of the list items.";
+};
+String RID_STR_GROUPBOX
+{
+ Text [ en-US ] = "Frame element";
+};
+String RID_STR_NAVIGATION
+{
+ Text [ en-US ] = "Navigation";
+};
+String RID_STR_NAVIGATIONBAR
+{
+ Text [ en-US ] = "Navigation bar";
+};
+String RID_STR_COLUMN
+{
+ Text [ en-US ] = "Col";
+};
+String RID_STR_UNDO_PROPERTY
+{
+ Text [ en-US ] = "Set property '#'";
+};
+String RID_STR_UNDO_CONTAINER_INSERT
+{
+ Text [ en-US ] = "Insert in container";
+};
+String RID_STR_UNDO_CONTAINER_REMOVE
+{
+ Text [ en-US ] = "Delete #";
+};
+String RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE
+{
+ Text [ en-US ] = "Delete # objects";
+};
+String RID_STR_UNDO_CONTAINER_REPLACE
+{
+ Text [ en-US ] = "Replace a container element";
+};
+String RID_STR_UNDO_DELETE_LOGICAL
+{
+ Text [ en-US ] = "Delete structure";
+};
+String RID_STR_UNDO_MODEL_REPLACE
+{
+ Text [ en-US ] = "Replace Control";
+};
+String RID_STR_DATE
+{
+ Text [ en-US ] = "Date";
+};
+String RID_STR_TIME
+{
+ Text [ en-US ] = "Time";
+};
+String RID_STR_PROPTITLE_PUSHBUTTON
+{
+ Text [ en-US ] = "Push Button";
+};
+String RID_STR_PROPTITLE_RADIOBUTTON
+{
+ Text [ en-US ] = "Option Button";
+};
+String RID_STR_PROPTITLE_CHECKBOX
+{
+ Text [ en-US ] = "Check Box";
+};
+String RID_STR_PROPTITLE_FIXEDTEXT
+{
+ Text [ en-US ] = "Label Field";
+};
+String RID_STR_PROPTITLE_GROUPBOX
+{
+ Text [ en-US ] = "Group Box";
+};
+String RID_STR_PROPTITLE_EDIT
+{
+ Text [ en-US ] = "Text Box";
+};
+String RID_STR_PROPTITLE_FORMATTED
+{
+ Text [ en-US ] = "Formatted Field";
+};
+String RID_STR_PROPTITLE_LISTBOX
+{
+ Text [ en-US ] = "List Box";
+};
+String RID_STR_PROPTITLE_COMBOBOX
+{
+ Text [ en-US ] = "Combo Box";
+};
+String RID_STR_PROPTITLE_IMAGEBUTTON
+{
+ Text [ en-US ] = "Image Button";
+};
+String RID_STR_PROPTITLE_IMAGECONTROL
+{
+ Text [ en-US ] = "Image Control";
+};
+String RID_STR_PROPTITLE_FILECONTROL
+{
+ Text [ en-US ] = "File Selection";
+};
+String RID_STR_PROPTITLE_DATEFIELD
+{
+ Text [ en-US ] = "Date Field";
+};
+String RID_STR_PROPTITLE_TIMEFIELD
+{
+ Text [ en-US ] = "Time Field";
+};
+String RID_STR_PROPTITLE_NUMERICFIELD
+{
+ Text [ en-US ] = "Numeric Field";
+};
+String RID_STR_PROPTITLE_CURRENCYFIELD
+{
+ Text [ en-US ] = "Currency Field";
+};
+String RID_STR_PROPTITLE_PATTERNFIELD
+{
+ Text [ en-US ] = "Pattern Field";
+};
+String RID_STR_PROPTITLE_DBGRID
+{
+ Text [ en-US ] = "Table Control ";
+};
+String RID_STR_PROPTITLE_SCROLLBAR
+{
+ Text [ en-US ] = "Scrollbar";
+};
+String RID_STR_PROPTITLE_SPINBUTTON
+{
+ Text [ en-US ] = "Spin Button";
+};
+String RID_STR_PROPTITLE_NAVBAR
+{
+ Text [ en-US ] = "Navigation Bar";
+};
+String RID_STR_PROPTITLE_MULTISELECT
+{
+ Text [ en-US ] = "Multiselection";
+};
+String RID_STR_NODATACONTROLS
+{
+ Text [ en-US ] = "No data-related controls in the current form!";
+};
+String RID_STR_POSTFIX_DATE
+{
+ Text [ en-US ] = " (Date)";
+};
+String RID_STR_POSTFIX_TIME
+{
+ Text [ en-US ] = " (Time)";
+};
+String RID_STR_FILTER_NAVIGATOR
+{
+ Text [ en-US ] = "Filter navigator";
+};
+
+String RID_STR_FILTER_FILTER_FOR
+{
+ Text [ en-US ] = "Filter for";
+};
+
+String RID_STR_FILTER_FILTER_OR
+{
+ Text [ en-US ] = "Or";
+};
+
+String RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY
+{
+ Text [ en-US ] = "Valid bound controls which can be used in the table view do not exist in the current form.";
+};
+String RID_STR_AUTOFIELD
+{
+ Text [ en-US ] = "<AutoField>";
+};
+
+QueryBox RID_QRY_SAVEMODIFIED
+{
+ Buttons = WB_YES_NO_CANCEL ;
+ DefButton = WB_DEF_YES ;
+ Message [ en-US ] = "The content of the current form has been modified.\nDo you want to save your changes?";
+};
+Resource RID_RSC_SQL_INTERNATIONAL
+{
+ String 1
+ {
+ Text [ en-US ] = "LIKE";
+ };
+ String 2
+ {
+ Text [ en-US ] = "NOT";
+ };
+ String 3
+ {
+ Text [ en-US ] = "EMPTY";
+ };
+ String 4
+ {
+ Text [ en-US ] = "TRUE";
+ };
+ String 5
+ {
+ Text [ en-US ] = "FALSE";
+ };
+ String 6
+ {
+ Text [ en-US ] = "IS";
+ };
+ String 7
+ {
+ Text [ en-US ] = "BETWEEN";
+ };
+ String 8
+ {
+ Text [ en-US ] = "OR";
+ };
+ String 9
+ {
+ Text [ en-US ] = "AND";
+ };
+ String 10
+ {
+ Text [ en-US ] = "Average";
+ };
+ String 11
+ {
+ Text [ en-US ] = "Count";
+ };
+ String 12
+ {
+ Text [ en-US ] = "Maximum";
+ };
+ String 13
+ {
+ Text [ en-US ] = "Minimum";
+ };
+ String 14
+ {
+ Text [ en-US ] = "Sum";
+ };
+ String 15
+ {
+ Text [ en-US ] = "Every";
+ };
+ String 16
+ {
+ Text [ en-US ] = "Any";
+ };
+ String 17
+ {
+ Text [ en-US ] = "Some";
+ };
+ String 18
+ {
+ Text [ en-US ] = "STDDEV_POP";
+ };
+ String 19
+ {
+ Text [ en-US ] = "STDDEV_SAMP";
+ };
+ String 20
+ {
+ Text [ en-US ] = "VAR_SAMP";
+ };
+ String 21
+ {
+ Text [ en-US ] = "VAR_POP";
+ };
+ String 22
+ {
+ Text [ en-US ] = "Collect";
+ };
+ String 23
+ {
+ Text [ en-US ] = "Fusion";
+ };
+ String 24
+ {
+ Text [ en-US ] = "Intersection";
+ };
+};
+
+String RID_STR_SVT_SQL_SYNTAX_ERROR
+{
+ /* ### ACHTUNG: Neuer Text in Resource? Syntaxfehler im SQL-Ausdruck : Fehlerhafte Syntax */
+ Text [ en-US ] = "Syntax error in SQL statement";
+};
+
+String RID_STR_SVT_SQL_SYNTAX_VALUE_NO_LIKE
+{
+ Text [ en-US ] = "The value #1 cannot be used with LIKE.";
+};
+
+String RID_STR_SVT_SQL_SYNTAX_FIELD_NO_LIKE
+{
+ Text [ en-US ] = "LIKE cannot be used with this field.";
+};
+
+String RID_STR_SVT_SQL_SYNTAX_ACCESS_DAT_NO_VALID
+{
+ Text [ en-US ] = "The value entered is not a valid date. Please enter a date in a valid format, for example, MM/DD/YY.";
+};
+
+String RID_STR_SVT_SQL_SYNTAX_INT_NO_VALID
+{
+ Text [ en-US ] = "The field cannot be compared with an integer.";
+};
+String RID_STR_SVT_SQL_SYNTAX_TABLE
+{
+ Text [ en-US ] = "The database does not contain a table named \"#\".";
+};
+String RID_STR_SVT_SQL_SYNTAX_TABLE_OR_QUERY
+{
+ Text [ en-US ] = "The database does contain neither a table nor a query named \"#\".";
+};
+String RID_STR_SVT_SQL_SYNTAX_TABLE_EXISTS
+{
+ Text [ en-US ] = "The database already contains a table or view with name \"#\".";
+};
+String RID_STR_SVT_SQL_SYNTAX_QUERY_EXISTS
+{
+ Text [ en-US ] = "The database already contains a query with name \"#\".";
+};
+String RID_STR_SVT_SQL_SYNTAX_COLUMN
+{
+ Text [ en-US ] = "The column \"#1\" is unknown in the table \"#2\".";
+};
+String RID_STR_SVT_SQL_SYNTAX_REAL_NO_VALID
+{
+ Text [ en-US ] = "The field cannot be compared with a floating point number.";
+};
+
+String RID_STR_SVT_SQL_SYNTAX_CRIT_NO_COMPARE
+{
+ Text [ en-US ] = "The entered criterion cannot be compared with this field.";
+};
+
+String RID_STR_DATANAVIGATOR
+{
+ Text [ en-US ] = "Data Navigator";
+};
+
+String RID_STR_READONLY_VIEW
+{
+ Text [ en-US ] = " (read-only)";
+};
+
+String RID_STR_ALREADYEXISTOVERWRITE
+{
+ Text [ en-US ] = "The file already exists. Overwrite?" ;
+};
+String RID_STR_OBJECT_LABEL
+{
+ Text [ en-US ] = "#object# label";
+};
diff --git a/svx/source/form/fmtextcontroldialogs.cxx b/svx/source/form/fmtextcontroldialogs.cxx
new file mode 100644
index 000000000000..388371ea7b49
--- /dev/null
+++ b/svx/source/form/fmtextcontroldialogs.cxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmtextcontroldialogs.hxx"
+#include <svx/dialmgr.hxx>
+#include <svx/dialogs.hrc>
+
+#include <editeng/eeitem.hxx>
+
+#include "flagsdef.hxx"
+#include <svl/intitem.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <svl/cjkoptions.hxx>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ //====================================================================
+ //= TextControlCharAttribDialog
+ //====================================================================
+ //--------------------------------------------------------------------
+ TextControlCharAttribDialog::TextControlCharAttribDialog( Window* pParent, const SfxItemSet& _rCoreSet, const SvxFontListItem& _rFontList )
+ :SfxTabDialog( pParent, SVX_RES( RID_SVXDLG_TEXTCONTROL_CHARATTR ), &_rCoreSet )
+ ,m_aFontList( _rFontList )
+ {
+ FreeResource();
+
+ AddTabPage( RID_SVXPAGE_CHAR_NAME);
+ AddTabPage( RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage( RID_SVXPAGE_CHAR_POSITION);
+ }
+
+ //--------------------------------------------------------------------
+ TextControlCharAttribDialog::~TextControlCharAttribDialog()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void TextControlCharAttribDialog::PageCreated( USHORT _nId, SfxTabPage& _rPage )
+ {
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+
+ switch( _nId )
+ {
+ case RID_SVXPAGE_CHAR_NAME:
+ aSet.Put (m_aFontList);
+ _rPage.PageCreated(aSet);
+ break;
+
+ case RID_SVXPAGE_CHAR_EFFECTS:
+ aSet.Put (SfxUInt16Item(SID_DISABLE_CTL,DISABLE_CASEMAP));
+ _rPage.PageCreated(aSet);
+ break;
+
+ case RID_SVXPAGE_CHAR_POSITION:
+ aSet.Put( SfxUInt32Item(SID_FLAG_TYPE, SVX_PREVIEW_CHARACTER) );
+ _rPage.PageCreated(aSet);
+ break;
+ }
+ }
+
+ //====================================================================
+ //= TextControlParaAttribDialog
+ //====================================================================
+ //--------------------------------------------------------------------
+ TextControlParaAttribDialog::TextControlParaAttribDialog( Window* _pParent, const SfxItemSet& _rCoreSet )
+ :SfxTabDialog( _pParent, SVX_RES( RID_SVXDLG_TEXTCONTROL_PARAATTR ), &_rCoreSet )
+ {
+ FreeResource();
+
+ AddTabPage( RID_SVXPAGE_STD_PARAGRAPH );
+ AddTabPage( RID_SVXPAGE_ALIGN_PARAGRAPH );
+
+ SvtCJKOptions aCJKOptions;
+ if( aCJKOptions.IsAsianTypographyEnabled() )
+ AddTabPage( RID_SVXPAGE_PARA_ASIAN );
+ else
+ RemoveTabPage( RID_SVXPAGE_PARA_ASIAN );
+
+ AddTabPage( RID_SVXPAGE_TABULATOR );
+ }
+
+ //--------------------------------------------------------------------
+ TextControlParaAttribDialog::~TextControlParaAttribDialog()
+ {
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmtextcontrolfeature.cxx b/svx/source/form/fmtextcontrolfeature.cxx
new file mode 100644
index 000000000000..c773881cb3da
--- /dev/null
+++ b/svx/source/form/fmtextcontrolfeature.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "fmtextcontrolfeature.hxx"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+
+ //====================================================================
+ //= FmTextControlFeature
+ //====================================================================
+ //--------------------------------------------------------------------
+ FmTextControlFeature::FmTextControlFeature( const Reference< XDispatch >& _rxDispatcher, const URL& _rFeatureURL, SfxSlotId _nSlotId, ISlotInvalidator* _pInvalidator )
+ :m_xDispatcher ( _rxDispatcher )
+ ,m_aFeatureURL ( _rFeatureURL )
+ ,m_nSlotId ( _nSlotId )
+ ,m_pInvalidator ( _pInvalidator )
+ ,m_bFeatureEnabled( false )
+ {
+ OSL_ENSURE( _rxDispatcher.is(), "FmTextControlFeature::FmTextControlFeature: invalid dispatcher!" );
+ OSL_ENSURE( m_nSlotId, "FmTextControlFeature::FmTextControlFeature: invalid slot id!" );
+ OSL_ENSURE( m_pInvalidator, "FmTextControlFeature::FmTextControlFeature: invalid invalidator!" );
+
+ osl_incrementInterlockedCount( &m_refCount );
+ try
+ {
+ m_xDispatcher->addStatusListener( this, m_aFeatureURL );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmTextControlFeature::FmTextControlFeature: caught an exception!" );
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ FmTextControlFeature::~FmTextControlFeature( )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void FmTextControlFeature::dispatch() const SAL_THROW(())
+ {
+ dispatch( Sequence< PropertyValue >( ) );
+ }
+
+ //--------------------------------------------------------------------
+ void FmTextControlFeature::dispatch( const Sequence< PropertyValue >& _rArgs ) const SAL_THROW(())
+ {
+ try
+ {
+ if ( m_xDispatcher.is() )
+ m_xDispatcher->dispatch( m_aFeatureURL, _rArgs );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmTextControlFeature::dispatch: caught an exception!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmTextControlFeature::statusChanged( const FeatureStateEvent& _rState ) throw (RuntimeException)
+ {
+ m_aFeatureState = _rState.State;
+ m_bFeatureEnabled = _rState.IsEnabled;
+
+ if ( m_pInvalidator )
+ m_pInvalidator->Invalidate( m_nSlotId );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmTextControlFeature::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
+ {
+ // nothing to do
+ }
+
+ //--------------------------------------------------------------------
+ void FmTextControlFeature::dispose() SAL_THROW(())
+ {
+ try
+ {
+ m_xDispatcher->removeStatusListener( this, m_aFeatureURL );
+ m_xDispatcher.clear();
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmTextControlFeature::dispose: caught an exception!" );
+ }
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmtextcontrolshell.cxx b/svx/source/form/fmtextcontrolshell.cxx
new file mode 100644
index 000000000000..a1a3f1592f68
--- /dev/null
+++ b/svx/source/form/fmtextcontrolshell.cxx
@@ -0,0 +1,1401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+#include "fmtextcontroldialogs.hxx"
+#include "fmtextcontrolfeature.hxx"
+#include "fmtextcontrolshell.hxx"
+#include "editeng/crsditem.hxx"
+#include "svx/dialmgr.hxx"
+#include "editeng/editeng.hxx"
+#include "editeng/eeitem.hxx"
+#include "svx/fmglob.hxx"
+#include "editeng/scriptspaceitem.hxx"
+#include "svx/svxids.hrc"
+#include "editeng/udlnitem.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/awt/XFocusListener.hpp>
+#include <com/sun/star/awt/XMouseListener.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/msgpool.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/sfxuno.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/itempool.hxx>
+#include <svl/languageoptions.hxx>
+#include <svtools/stringtransfer.hxx>
+#include <svl/whiter.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/msgbox.hxx>
+#include <vcl/outdev.hxx>
+#include <osl/mutex.hxx>
+
+#include <memory>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::form;
+ using namespace ::com::sun::star::form::runtime;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+
+ //====================================================================
+ typedef USHORT WhichId;
+
+ //====================================================================
+ static SfxSlotId pTextControlSlots[] =
+ {
+ SID_CLIPBOARD_FORMAT_ITEMS,
+ SID_CUT,
+ SID_COPY,
+ SID_PASTE,
+ SID_SELECTALL,
+// SID_ATTR_TABSTOP, /* 2 */
+ SID_ATTR_CHAR_FONT,
+ SID_ATTR_CHAR_POSTURE,
+ SID_ATTR_CHAR_WEIGHT,
+ SID_ATTR_CHAR_SHADOWED,
+ SID_ATTR_CHAR_WORDLINEMODE,
+ SID_ATTR_CHAR_CONTOUR,
+ SID_ATTR_CHAR_STRIKEOUT,
+ SID_ATTR_CHAR_UNDERLINE,
+ SID_ATTR_CHAR_FONTHEIGHT,
+ SID_ATTR_CHAR_COLOR,
+ SID_ATTR_CHAR_KERNING,
+ SID_ATTR_CHAR_LANGUAGE, /* 20 */
+ SID_ATTR_CHAR_ESCAPEMENT,
+ SID_ATTR_PARA_ADJUST, /* 28 */
+ SID_ATTR_PARA_ADJUST_LEFT,
+ SID_ATTR_PARA_ADJUST_RIGHT,
+ SID_ATTR_PARA_ADJUST_CENTER,
+ SID_ATTR_PARA_ADJUST_BLOCK,
+ SID_ATTR_PARA_LINESPACE, /* 33 */
+ SID_ATTR_PARA_LINESPACE_10,
+ SID_ATTR_PARA_LINESPACE_15,
+ SID_ATTR_PARA_LINESPACE_20,
+ SID_ATTR_LRSPACE, /* 48 */
+ SID_ATTR_ULSPACE, /* 49 */
+ SID_ATTR_CHAR_AUTOKERN,
+ SID_SET_SUPER_SCRIPT,
+ SID_SET_SUB_SCRIPT,
+ SID_CHAR_DLG,
+ SID_PARA_DLG,
+// SID_TEXTDIRECTION_LEFT_TO_RIGHT, /* 907 */
+// SID_TEXTDIRECTION_TOP_TO_BOTTOM,
+ SID_ATTR_CHAR_SCALEWIDTH, /* 911 */
+ SID_ATTR_CHAR_RELIEF,
+ SID_ATTR_PARA_LEFT_TO_RIGHT, /* 950 */
+ SID_ATTR_PARA_RIGHT_TO_LEFT,
+ SID_ATTR_CHAR_OVERLINE,
+ 0
+ };
+
+ // slots which we are not responsible for on the SfxShell level, but
+ // need to handle during the "paragraph attributes" and/or "character
+ // attributes" dialogs
+ static SfxSlotId pDialogSlots[] =
+ {
+ SID_ATTR_TABSTOP,
+ SID_ATTR_PARA_HANGPUNCTUATION,
+ SID_ATTR_PARA_FORBIDDEN_RULES,
+ SID_ATTR_PARA_SCRIPTSPACE,
+ SID_ATTR_CHAR_LATIN_LANGUAGE,
+ SID_ATTR_CHAR_CJK_LANGUAGE,
+ SID_ATTR_CHAR_CTL_LANGUAGE,
+ SID_ATTR_CHAR_LATIN_FONT,
+ SID_ATTR_CHAR_CJK_FONT,
+ SID_ATTR_CHAR_CTL_FONT,
+ SID_ATTR_CHAR_LATIN_FONTHEIGHT,
+ SID_ATTR_CHAR_CJK_FONTHEIGHT,
+ SID_ATTR_CHAR_CTL_FONTHEIGHT,
+ SID_ATTR_CHAR_LATIN_WEIGHT,
+ SID_ATTR_CHAR_CJK_WEIGHT,
+ SID_ATTR_CHAR_CTL_WEIGHT,
+ SID_ATTR_CHAR_LATIN_POSTURE,
+ SID_ATTR_CHAR_CJK_POSTURE,
+ SID_ATTR_CHAR_CTL_POSTURE,
+ SID_ATTR_CHAR_EMPHASISMARK,
+ 0
+ };
+
+ //====================================================================
+ //= FmFocusListenerAdapter
+ //====================================================================
+ typedef ::cppu::WeakImplHelper1 < XFocusListener
+ > FmFocusListenerAdapter_Base;
+ class FmFocusListenerAdapter : public FmFocusListenerAdapter_Base
+ {
+ private:
+ IFocusObserver* m_pObserver;
+ Reference< XWindow > m_xWindow;
+
+ public:
+ FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver );
+
+ // clean up the instance
+ void dispose();
+
+ protected:
+ ~FmFocusListenerAdapter();
+
+ protected:
+ virtual void SAL_CALL focusGained( const FocusEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL focusLost( const FocusEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
+ };
+
+ //--------------------------------------------------------------------
+ DBG_NAME( FmFocusListenerAdapter )
+ //--------------------------------------------------------------------
+ FmFocusListenerAdapter::FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver )
+ :m_pObserver( _pObserver )
+ ,m_xWindow( _rxControl, UNO_QUERY )
+ {
+ DBG_CTOR( FmFocusListenerAdapter, NULL );
+
+ DBG_ASSERT( m_xWindow.is(), "FmFocusListenerAdapter::FmFocusListenerAdapter: invalid control!" );
+ osl_incrementInterlockedCount( &m_refCount );
+ {
+ try
+ {
+ if ( m_xWindow.is() )
+ m_xWindow->addFocusListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ FmFocusListenerAdapter::~FmFocusListenerAdapter()
+ {
+ acquire();
+ dispose();
+
+ DBG_DTOR( FmFocusListenerAdapter, NULL );
+ }
+
+ //--------------------------------------------------------------------
+ void FmFocusListenerAdapter::dispose()
+ {
+ if ( m_xWindow.is() )
+ {
+ m_xWindow->removeFocusListener( this );
+ m_xWindow.clear();
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmFocusListenerAdapter::focusGained( const FocusEvent& e ) throw (RuntimeException)
+ {
+ if ( m_pObserver )
+ m_pObserver->focusGained( e );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmFocusListenerAdapter::focusLost( const FocusEvent& e ) throw (RuntimeException)
+ {
+ if ( m_pObserver )
+ m_pObserver->focusLost( e );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmFocusListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
+ {
+ (void)Source;
+ DBG_ASSERT( Source.Source == m_xWindow, "FmFocusListenerAdapter::disposing: where did this come from?" );
+ m_xWindow.clear();
+ }
+
+ //====================================================================
+ //= FmMouseListenerAdapter
+ //====================================================================
+ typedef ::cppu::WeakImplHelper1 < XMouseListener
+ > FmMouseListenerAdapter_Base;
+ class FmMouseListenerAdapter : public FmMouseListenerAdapter_Base
+ {
+ private:
+ IContextRequestObserver* m_pObserver;
+ Reference< XWindow > m_xWindow;
+
+ public:
+ FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver );
+
+ // clean up the instance
+ void dispose();
+
+ protected:
+ ~FmMouseListenerAdapter();
+
+ protected:
+ virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) throw (RuntimeException);
+ virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
+ };
+
+ //====================================================================
+ //= FmMouseListenerAdapter
+ //====================================================================
+ //--------------------------------------------------------------------
+ DBG_NAME( FmMouseListenerAdapter )
+ //--------------------------------------------------------------------
+ FmMouseListenerAdapter::FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver )
+ :m_pObserver( _pObserver )
+ ,m_xWindow( _rxControl, UNO_QUERY )
+ {
+ DBG_CTOR( FmMouseListenerAdapter, NULL );
+
+ DBG_ASSERT( m_xWindow.is(), "FmMouseListenerAdapter::FmMouseListenerAdapter: invalid control!" );
+ osl_incrementInterlockedCount( &m_refCount );
+ {
+ try
+ {
+ if ( m_xWindow.is() )
+ m_xWindow->addMouseListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ FmMouseListenerAdapter::~FmMouseListenerAdapter()
+ {
+ acquire();
+ dispose();
+
+ DBG_DTOR( FmMouseListenerAdapter, NULL );
+ }
+
+ //--------------------------------------------------------------------
+ void FmMouseListenerAdapter::dispose()
+ {
+ if ( m_xWindow.is() )
+ {
+ m_xWindow->removeMouseListener( this );
+ m_xWindow.clear();
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmMouseListenerAdapter::mousePressed( const awt::MouseEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+ // is this a request for a context menu?
+ if ( _rEvent.PopupTrigger )
+ {
+ if ( m_pObserver )
+ m_pObserver->contextMenuRequested( _rEvent );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmMouseListenerAdapter::mouseReleased( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ // not interested in
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmMouseListenerAdapter::mouseEntered( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ // not interested in
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmMouseListenerAdapter::mouseExited( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ // not interested in
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FmMouseListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
+ {
+ (void)Source;
+ DBG_ASSERT( Source.Source == m_xWindow, "FmMouseListenerAdapter::disposing: where did this come from?" );
+ m_xWindow.clear();
+ }
+
+ //====================================================================
+ //= FmTextControlShell
+ //====================================================================
+ //------------------------------------------------------------------------
+ namespace
+ {
+ //....................................................................
+ void lcl_translateUnoStateToItem( SfxSlotId _nSlot, const Any& _rUnoState, SfxItemSet& _rSet )
+ {
+ WhichId nWhich = _rSet.GetPool()->GetWhich( _nSlot );
+ if ( !_rUnoState.hasValue() )
+ {
+ if ( ( _nSlot != SID_CUT )
+ && ( _nSlot != SID_COPY )
+ && ( _nSlot != SID_PASTE )
+ )
+ {
+ _rSet.InvalidateItem( nWhich );
+ }
+ }
+ else
+ {
+ switch ( _rUnoState.getValueType().getTypeClass() )
+ {
+ case TypeClass_BOOLEAN:
+ {
+ sal_Bool bState = sal_False;
+ _rUnoState >>= bState;
+ if ( _nSlot == SID_ATTR_PARA_SCRIPTSPACE )
+ _rSet.Put( SvxScriptSpaceItem( bState, nWhich ) );
+ else
+ _rSet.Put( SfxBoolItem( nWhich, bState ) );
+ }
+ break;
+
+ default:
+ {
+ Sequence< PropertyValue > aComplexState;
+ if ( _rUnoState >>= aComplexState )
+ {
+ if ( !aComplexState.getLength() )
+ _rSet.InvalidateItem( nWhich );
+ else
+ {
+ SfxAllItemSet aAllItems( _rSet );
+ TransformParameters( _nSlot, aComplexState, aAllItems );
+ const SfxPoolItem* pTransformed = aAllItems.GetItem( nWhich );
+ OSL_ENSURE( pTransformed, "lcl_translateUnoStateToItem: non-empty parameter sequence leading to empty item?" );
+ if ( pTransformed )
+ _rSet.Put( *pTransformed );
+ else
+ _rSet.InvalidateItem( nWhich );
+ }
+ }
+ else
+ {
+ DBG_ERROR( "lcl_translateUnoStateToItem: invalid state!" );
+ }
+ }
+ }
+ }
+ }
+
+ //....................................................................
+ ::rtl::OUString lcl_getUnoSlotName( SfxApplication&, SfxSlotId _nSlotId )
+ {
+ ::rtl::OUString sSlotUnoName;
+
+ SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
+ const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
+
+ const sal_Char* pAsciiUnoName = NULL;
+ if ( pSlot )
+ {
+ pAsciiUnoName = pSlot->GetUnoName();
+ }
+ else
+ {
+ // some hard-coded slots, which do not have a UNO name at SFX level, but which
+ // we nevertheless need to transport via UNO mechanisms, so we need a name
+ switch ( _nSlotId )
+ {
+ case SID_ATTR_PARA_HANGPUNCTUATION: pAsciiUnoName = "AllowHangingPunctuation"; break;
+ case SID_ATTR_PARA_FORBIDDEN_RULES: pAsciiUnoName = "ApplyForbiddenCharacterRules"; break;
+ case SID_ATTR_PARA_SCRIPTSPACE: pAsciiUnoName = "UseScriptSpacing"; break;
+ }
+ }
+
+ if ( pAsciiUnoName )
+ {
+ sSlotUnoName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) );
+ sSlotUnoName += ::rtl::OUString::createFromAscii( pAsciiUnoName );
+ }
+#if OSL_DEBUG_LEVEL > 0
+ else
+ {
+ ::rtl::OString sMessage( "lcl_getUnoSlotName: invalid slot id, or invalid slot, or no UNO name!\n" );
+ sMessage += "(slot id: ";
+ sMessage += ::rtl::OString::valueOf( (sal_Int32)_nSlotId );
+ sMessage += ")";
+ DBG_ERROR( sMessage );
+ }
+#endif
+ return sSlotUnoName;
+ }
+
+ //....................................................................
+ bool lcl_determineReadOnly( const Reference< XControl >& _rxControl )
+ {
+ bool bIsReadOnlyModel = true;
+ try
+ {
+ Reference< XPropertySet > xModelProps;
+ if ( _rxControl.is() )
+ xModelProps = xModelProps.query( _rxControl->getModel() );
+ Reference< XPropertySetInfo > xModelPropInfo;
+ if ( xModelProps.is() )
+ xModelPropInfo = xModelProps->getPropertySetInfo();
+
+ if ( !xModelPropInfo.is() || !xModelPropInfo->hasPropertyByName( FM_PROP_READONLY ) )
+ bIsReadOnlyModel = true;
+ else
+ {
+ sal_Bool bReadOnly = sal_True;
+ xModelProps->getPropertyValue( FM_PROP_READONLY ) >>= bReadOnly;
+ bIsReadOnlyModel = bReadOnly;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return bIsReadOnlyModel;
+ }
+
+ //....................................................................
+ static Window* lcl_getWindow( const Reference< XControl >& _rxControl )
+ {
+ Window* pWindow = NULL;
+ try
+ {
+ Reference< XWindowPeer > xControlPeer;
+ if ( _rxControl.is() )
+ xControlPeer = _rxControl->getPeer();
+ if ( xControlPeer.is() )
+ pWindow = VCLUnoHelper::GetWindow( xControlPeer );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return pWindow;
+ }
+
+ //....................................................................
+ bool lcl_isRichText( const Reference< XControl >& _rxControl )
+ {
+ if ( !_rxControl.is() )
+ return false;
+
+ bool bIsRichText = false;
+ try
+ {
+ Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI;
+ if ( xModelProps.is() )
+ xPSI = xModelProps->getPropertySetInfo();
+ ::rtl::OUString sRichTextPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RichText" ) );
+ if ( xPSI.is() && xPSI->hasPropertyByName( sRichTextPropertyName ) )
+ {
+ OSL_VERIFY( xModelProps->getPropertyValue( sRichTextPropertyName ) >>= bIsRichText );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return bIsRichText;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ FmTextControlShell::FmTextControlShell( SfxViewFrame* _pFrame )
+ :m_bActiveControl( false )
+ ,m_bActiveControlIsReadOnly( true )
+ ,m_bActiveControlIsRichText( false )
+ ,m_pViewFrame( _pFrame )
+ ,m_rBindings( _pFrame->GetBindings() )
+ ,m_bNeedClipboardInvalidation( true )
+ {
+ m_aClipboardInvalidation.SetTimeoutHdl( LINK( this, FmTextControlShell, OnInvalidateClipboard ) );
+ m_aClipboardInvalidation.SetTimeout( 200 );
+ }
+
+ //------------------------------------------------------------------------
+ FmTextControlShell::~FmTextControlShell()
+ {
+ dispose();
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( FmTextControlShell, OnInvalidateClipboard, void*, /*_pNotInterestedIn*/ )
+ {
+ if ( m_bNeedClipboardInvalidation )
+ {
+ DBG_TRACE( "FmTextControlShell::ClipBoard: invalidating clipboard slots" );
+ m_rBindings.Invalidate( SID_CUT );
+ m_rBindings.Invalidate( SID_COPY );
+ m_rBindings.Invalidate( SID_PASTE );
+ m_bNeedClipboardInvalidation = false;
+ }
+ return 0L;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::transferFeatureStatesToItemSet( ControlFeatures& _rDispatchers, SfxAllItemSet& _rSet, bool _bTranslateLatin )
+ {
+ SfxItemPool& rPool = *_rSet.GetPool();
+
+ for ( ControlFeatures::const_iterator aFeature = _rDispatchers.begin();
+ aFeature != _rDispatchers.end();
+ ++aFeature
+ )
+ {
+ SfxSlotId nSlotId( aFeature->first );
+ #if OSL_DEBUG_LEVEL > 0
+ ::rtl::OUString sUnoSlotName;
+ if ( SFX_APP() )
+ sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotId );
+ else
+ sUnoSlotName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "<unknown>" ) );
+ ::rtl::OString sUnoSlotNameAscii( "\"" );
+ sUnoSlotNameAscii += ::rtl::OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
+ sUnoSlotNameAscii += "\"";
+ #endif
+
+ if ( _bTranslateLatin )
+ {
+ // A rich text control offers a dispatcher for the "Font" slot/feature.
+ // Sadly, the semantics of the dispatches is that the feature "Font" depends
+ // on the current cursor position: If it's on latin text, it's the "latin font"
+ // which is set up at the control. If it's on CJK text, it's the "CJK font", and
+ // aequivalent for "CTL font".
+ // The same holds for some other font related features/slots.
+ // Thus, we have separate dispatches for "Latin Font", "Latin Font Size", etc,
+ // which are only "virtual", in a sense that there exist no item with this id.
+ // So when we encounter such a dispatcher for, say, "Latin Font", we need to
+ // put an item into the set which has the "Font" id.
+
+ switch ( nSlotId )
+ {
+ case SID_ATTR_CHAR_LATIN_FONT: nSlotId = SID_ATTR_CHAR_FONT; break;
+ case SID_ATTR_CHAR_LATIN_FONTHEIGHT:nSlotId = SID_ATTR_CHAR_FONTHEIGHT; break;
+ case SID_ATTR_CHAR_LATIN_LANGUAGE: nSlotId = SID_ATTR_CHAR_LANGUAGE; break;
+ case SID_ATTR_CHAR_LATIN_POSTURE: nSlotId = SID_ATTR_CHAR_POSTURE; break;
+ case SID_ATTR_CHAR_LATIN_WEIGHT: nSlotId = SID_ATTR_CHAR_WEIGHT; break;
+ }
+ }
+
+ WhichId nWhich = rPool.GetWhich( nSlotId );
+ bool bIsInPool = rPool.IsInRange( nWhich );
+ if ( bIsInPool )
+ {
+ #if OSL_DEBUG_LEVEL > 0
+ bool bFeatureIsEnabled = aFeature->second->isFeatureEnabled();
+ ::rtl::OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
+ sMessage += sUnoSlotNameAscii;
+ if ( !bFeatureIsEnabled )
+ sMessage += " (disabled)";
+ DBG_TRACE( sMessage );
+ #endif
+
+ lcl_translateUnoStateToItem( nSlotId, aFeature->second->getFeatureState(), _rSet );
+ }
+ #if OSL_DEBUG_LEVEL > 0
+ else
+ {
+ ::rtl::OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
+ sMessage += sUnoSlotNameAscii;
+ sMessage += ", but could not translate it into an item!";
+ DBG_TRACE( sMessage );
+ }
+ #endif
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::executeAttributeDialog( AttributeSet _eSet, SfxRequest& _rReq )
+ {
+ const SvxFontListItem* pFontList = PTR_CAST( SvxFontListItem, m_pViewFrame->GetObjectShell()->GetItem( SID_ATTR_CHAR_FONTLIST ) );
+ DBG_ASSERT( pFontList, "FmTextControlShell::executeAttributeDialog: no font list item!" );
+ if ( !pFontList )
+ return;
+
+ SfxItemPool* pPool = EditEngine::CreatePool();
+ pPool->FreezeIdRanges();
+ ::std::auto_ptr< SfxItemSet > pPureItems( new SfxItemSet( *pPool ) );
+
+ // put the current states of the items into the set
+ ::std::auto_ptr< SfxAllItemSet > pCurrentItems( new SfxAllItemSet( *pPureItems ) );
+ transferFeatureStatesToItemSet( m_aControlFeatures, *pCurrentItems );
+
+ // additional items, which we are not responsible for at the SfxShell level,
+ // but which need to be forwarded to the dialog, anyway
+ ControlFeatures aAdditionalFestures;
+ fillFeatureDispatchers( m_xActiveControl, pDialogSlots, aAdditionalFestures );
+ transferFeatureStatesToItemSet( aAdditionalFestures, *pCurrentItems, true );
+
+ ::std::auto_ptr< SfxTabDialog > pDialog ( _eSet == eCharAttribs
+ ? static_cast< SfxTabDialog* >( new TextControlCharAttribDialog( NULL, *pCurrentItems, *pFontList ) )
+ : static_cast< SfxTabDialog* >( new TextControlParaAttribDialog( NULL, *pCurrentItems ) ) );
+ if ( RET_OK == pDialog->Execute() )
+ {
+ const SfxItemSet& rModifiedItems = *pDialog->GetOutputItemSet();
+ for ( WhichId nWhich = pPool->GetFirstWhich(); nWhich <= pPool->GetLastWhich(); ++nWhich )
+ {
+ if ( rModifiedItems.GetItemState( nWhich ) == SFX_ITEM_SET )
+ {
+ SfxSlotId nSlotForItemSet = pPool->GetSlotId( nWhich );
+ const SfxPoolItem* pModifiedItem = rModifiedItems.GetItem( nWhich );
+
+
+ SfxSlotId nSlotForDispatcher = nSlotForItemSet;
+ switch ( nSlotForDispatcher )
+ {
+ case SID_ATTR_CHAR_FONT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONT; break;
+ case SID_ATTR_CHAR_FONTHEIGHT:nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONTHEIGHT; break;
+ case SID_ATTR_CHAR_LANGUAGE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_LANGUAGE; break;
+ case SID_ATTR_CHAR_POSTURE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_POSTURE; break;
+ case SID_ATTR_CHAR_WEIGHT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_WEIGHT; break;
+ }
+
+ // do we already have a dispatcher for this slot/feature?
+ ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlotForDispatcher );
+ bool bFound = aFeaturePos != m_aControlFeatures.end( );
+
+ if ( !bFound )
+ {
+ aFeaturePos = aAdditionalFestures.find( nSlotForDispatcher );
+ bFound = aFeaturePos != aAdditionalFestures.end( );
+ }
+
+ if ( bFound )
+ {
+ Sequence< PropertyValue > aArgs;
+ // temporarily put the modified item into a "clean" set,
+ // and let TransformItems calc the respective UNO parameters
+ pPureItems->Put( *pModifiedItem );
+ TransformItems( nSlotForItemSet, *pPureItems, aArgs );
+ pPureItems->ClearItem( nWhich );
+
+ if ( ( nSlotForItemSet == SID_ATTR_PARA_HANGPUNCTUATION )
+ || ( nSlotForItemSet == SID_ATTR_PARA_FORBIDDEN_RULES )
+ || ( nSlotForItemSet == SID_ATTR_PARA_SCRIPTSPACE )
+ )
+ {
+ // these are no UNO slots, they need special handling since TransformItems cannot
+ // handle them
+ DBG_ASSERT( aArgs.getLength() == 0, "FmTextControlShell::executeAttributeDialog: these are no UNO slots - are they?" );
+
+ const SfxBoolItem* pBoolItem = PTR_CAST( SfxBoolItem, pModifiedItem );
+ DBG_ASSERT( pBoolItem, "FmTextControlShell::executeAttributeDialog: no bool item?!" );
+ if ( pBoolItem )
+ {
+ aArgs.realloc( 1 );
+ aArgs[ 0 ].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enable" ) );
+ aArgs[ 0 ].Value <<= (sal_Bool)pBoolItem->GetValue();
+ }
+ }
+
+ // dispatch this
+ aFeaturePos->second->dispatch( aArgs );
+ }
+ #if OSL_DEBUG_LEVEL > 0
+ else
+ {
+ ::rtl::OString sError( "FmTextControShell::executeAttributeDialog: Could not handle the following item:" );
+ sError += "\n SlotID: "; sError += ::rtl::OString::valueOf( (sal_Int32)nSlotForItemSet );
+ sError += "\n WhichID: "; sError += ::rtl::OString::valueOf( (sal_Int32)nWhich );
+ sError += "\n UNO name: ";
+
+ ::rtl::OUString sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotForItemSet );
+ if ( sUnoSlotName.getLength() )
+ sError += ::rtl::OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
+ else
+ sError += "unknown (no SfxSlot)";
+ DBG_ERROR( sError.getStr() );
+ }
+ #endif
+ }
+ }
+ _rReq.Done( rModifiedItems );
+ }
+
+ pDialog.reset();
+ pCurrentItems.reset();
+ pPureItems.reset();
+ SfxItemPool::Free(pPool);
+ }
+
+ //------------------------------------------------------------------------
+ bool FmTextControlShell::executeSelectAll( )
+ {
+ try
+ {
+ if ( m_xActiveTextComponent.is() )
+ {
+ sal_Int32 nTextLen = m_xActiveTextComponent->getText().getLength();
+ m_xActiveTextComponent->setSelection( awt::Selection( 0, nTextLen ) );
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return false; // not handled
+ }
+
+ //------------------------------------------------------------------------
+ bool FmTextControlShell::executeClipboardSlot( SfxSlotId _nSlot )
+ {
+ try
+ {
+ if ( m_xActiveTextComponent.is() )
+ {
+ switch ( _nSlot )
+ {
+ case SID_COPY:
+ case SID_CUT:
+ {
+ ::rtl::OUString sSelectedText( m_xActiveTextComponent->getSelectedText() );
+ ::svt::OStringTransfer::CopyString( sSelectedText, lcl_getWindow( m_xActiveControl ) );
+ if ( SID_CUT == _nSlot )
+ {
+ awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
+ m_xActiveTextComponent->insertText( aSelection, ::rtl::OUString() );
+ }
+ }
+ break;
+ case SID_PASTE:
+ {
+ ::rtl::OUString sClipboardContent;
+ OSL_VERIFY( ::svt::OStringTransfer::PasteString( sClipboardContent, lcl_getWindow( m_xActiveControl ) ) );
+ awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
+ m_xActiveTextComponent->insertText( aSelection, sClipboardContent );
+ }
+ break;
+ default:
+ OSL_ENSURE( sal_False, "FmTextControlShell::executeClipboardSlot: invalid slot!" );
+ }
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return false; // not handled
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::ExecuteTextAttribute( SfxRequest& _rReq )
+ {
+ SfxSlotId nSlot = _rReq.GetSlot();
+
+ ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
+ if ( aFeaturePos == m_aControlFeatures.end() )
+ {
+ // special slots
+ switch ( nSlot )
+ {
+ case SID_CHAR_DLG:
+ executeAttributeDialog( eCharAttribs, _rReq );
+ break;
+
+ case SID_PARA_DLG:
+ executeAttributeDialog( eParaAttribs, _rReq );
+ break;
+
+ case SID_SELECTALL:
+ executeSelectAll();
+ break;
+
+ case SID_CUT:
+ case SID_COPY:
+ case SID_PASTE:
+ executeClipboardSlot( nSlot );
+ break;
+
+ default:
+ DBG_ASSERT( aFeaturePos != m_aControlFeatures.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" );
+ return;
+ }
+ }
+ else
+ {
+ // slots which are dispatched to the control
+
+ switch ( nSlot )
+ {
+ case SID_ATTR_CHAR_STRIKEOUT:
+ case SID_ATTR_CHAR_UNDERLINE:
+ case SID_ATTR_CHAR_OVERLINE:
+ {
+ SfxItemSet aToggled( *_rReq.GetArgs() );
+
+ lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), aToggled );
+ WhichId nWhich = aToggled.GetPool()->GetWhich( nSlot );
+ const SfxPoolItem* pItem = aToggled.GetItem( nWhich );
+ if ( ( SID_ATTR_CHAR_UNDERLINE == nSlot ) || ( SID_ATTR_CHAR_OVERLINE == nSlot ) )
+ {
+ const SvxOverlineItem* pTextLine = PTR_CAST( SvxOverlineItem, pItem );
+ DBG_ASSERT( pTextLine, "FmTextControlShell::ExecuteTextAttribute: ooops - no underline/overline item!" );
+ if ( pTextLine )
+ {
+ FontUnderline eTL = pTextLine->GetLineStyle();
+ if ( SID_ATTR_CHAR_UNDERLINE == nSlot ) {
+ aToggled.Put( SvxUnderlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
+ } else {
+ aToggled.Put( SvxOverlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
+ }
+ }
+ }
+ else
+ {
+ const SvxCrossedOutItem* pCrossedOut = PTR_CAST( SvxCrossedOutItem, pItem );
+ DBG_ASSERT( pCrossedOut, "FmTextControlShell::ExecuteTextAttribute: ooops - no CrossedOut item!" );
+ if ( pCrossedOut )
+ {
+ FontStrikeout eFS = pCrossedOut->GetStrikeout();
+ aToggled.Put( SvxCrossedOutItem( eFS == STRIKEOUT_SINGLE ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, nWhich ) );
+ }
+ }
+
+ Sequence< PropertyValue > aArguments;
+ TransformItems( nSlot, aToggled, aArguments );
+ aFeaturePos->second->dispatch( aArguments );
+ }
+ break;
+
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ case SID_ATTR_CHAR_FONT:
+ case SID_ATTR_CHAR_POSTURE:
+ case SID_ATTR_CHAR_WEIGHT:
+ case SID_ATTR_CHAR_SHADOWED:
+ case SID_ATTR_CHAR_CONTOUR:
+ case SID_SET_SUPER_SCRIPT:
+ case SID_SET_SUB_SCRIPT:
+ {
+ const SfxItemSet* pArgs = _rReq.GetArgs();
+ Sequence< PropertyValue > aArgs;
+ if ( pArgs )
+ TransformItems( nSlot, *pArgs, aArgs );
+ aFeaturePos->second->dispatch( aArgs );
+ }
+ break;
+
+ default:
+ if ( aFeaturePos->second->isFeatureEnabled() )
+ aFeaturePos->second->dispatch();
+ break;
+ }
+ }
+ _rReq.Done();
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::GetTextAttributeState( SfxItemSet& _rSet )
+ {
+ SfxWhichIter aIter( _rSet );
+ sal_uInt16 nSlot = aIter.FirstWhich();
+ while ( nSlot )
+ {
+ if ( ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT )
+ || ( nSlot == SID_ATTR_PARA_RIGHT_TO_LEFT )
+ )
+ {
+ if ( !SvtLanguageOptions().IsCTLFontEnabled() )
+ {
+ _rSet.DisableItem( nSlot );
+ nSlot = aIter.NextWhich();
+ continue;
+ }
+ }
+
+ ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
+ if ( aFeaturePos != m_aControlFeatures.end() )
+ {
+ if ( aFeaturePos->second->isFeatureEnabled() )
+ lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), _rSet );
+ else
+ _rSet.DisableItem( nSlot );
+ }
+ else
+ {
+ bool bDisable = false;
+
+ bool bNeedWriteableControl = false;
+ bool bNeedTextComponent = false;
+ bool bNeedSelection = false;
+
+ switch ( nSlot )
+ {
+ case SID_CHAR_DLG:
+ case SID_PARA_DLG:
+ bDisable |= m_aControlFeatures.empty();
+ bNeedWriteableControl = true;
+ break;
+
+ case SID_CUT:
+ bNeedSelection = true;
+ bNeedTextComponent = true;
+ bNeedWriteableControl = true;
+ DBG_TRACE( "FmTextControlShell::ClipBoard: need to invalidate again" );
+ m_bNeedClipboardInvalidation = true;
+ break;
+
+ case SID_PASTE:
+ {
+ Window* pActiveControlVCLWindow = lcl_getWindow( m_xActiveControl );
+ if ( pActiveControlVCLWindow )
+ {
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pActiveControlVCLWindow) );
+ bDisable |= !aDataHelper.HasFormat( SOT_FORMAT_STRING );
+ }
+ else
+ bDisable |= true;
+
+ bNeedTextComponent = true;
+ bNeedWriteableControl = true;
+ }
+ break;
+
+ case SID_COPY:
+ bNeedTextComponent = true;
+ bNeedSelection = true;
+ break;
+
+ case SID_SELECTALL:
+ bNeedTextComponent = true;
+ break;
+
+ default:
+ // slot is unknown at all
+ bDisable |= true;
+ break;
+ }
+ OSL_POSTCOND( !bNeedSelection || bNeedTextComponent, "FmTextControlShell::GetTextAttributeState: bNeedSelection should imply bNeedTextComponent!" );
+
+ if ( !bDisable && bNeedWriteableControl )
+ bDisable |= !IsActiveControl( ) || m_bActiveControlIsReadOnly;
+
+ if ( !bDisable && bNeedTextComponent )
+ bDisable |= !m_xActiveTextComponent.is();
+
+ if ( !bDisable && bNeedSelection )
+ {
+ awt::Selection aSelection = m_xActiveTextComponent->getSelection();
+ bDisable |= aSelection.Min == aSelection.Max;
+ }
+
+ if ( bDisable )
+ _rSet.DisableItem( nSlot );
+ }
+
+ nSlot = aIter.NextWhich();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ bool FmTextControlShell::IsActiveControl( bool _bCountRichTextOnly ) const
+ {
+ if ( _bCountRichTextOnly && !m_bActiveControlIsRichText )
+ return false;
+
+ return m_bActiveControl;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::dispose()
+ {
+ if ( IsActiveControl() )
+ controlDeactivated();
+ if ( isControllerListening() )
+ stopControllerListening();
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::designModeChanged( bool /*_bNewDesignMode*/ )
+ {
+ m_rBindings.Invalidate( pTextControlSlots );
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::formActivated( const Reference< XFormController >& _rxController )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OString sTrace( "FmTextControlShell::formActivated: 0x" );
+ sTrace += ::rtl::OString::valueOf( (sal_IntPtr)_rxController.get(), 16 );
+ DBG_TRACE( sTrace );
+#endif
+
+ DBG_ASSERT( _rxController.is(), "FmTextControlShell::formActivated: invalid controller!" );
+ if ( !_rxController.is() )
+ return;
+
+ // sometimes, a form controller notifies activations, even if it's already activated
+ if ( m_xActiveController == _rxController )
+ return;
+
+ try
+ {
+ startControllerListening( _rxController );
+ controlActivated( _rxController->getCurrentControl() );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::formDeactivated( const Reference< XFormController >& _rxController )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OString sTrace( "FmTextControlShell::formDeactivated: 0x" );
+ sTrace += ::rtl::OString::valueOf( (sal_IntPtr)_rxController.get(), 16 );
+ DBG_TRACE( sTrace );
+#endif
+ (void)_rxController;
+
+ if ( IsActiveControl() )
+ controlDeactivated();
+ if ( isControllerListening() )
+ stopControllerListening();
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::startControllerListening( const Reference< XFormController >& _rxController )
+ {
+ OSL_PRECOND( _rxController.is(), "FmTextControlShell::startControllerListening: invalid controller!" );
+ if ( !_rxController.is() )
+ return;
+
+ OSL_PRECOND( !isControllerListening(), "FmTextControlShell::startControllerListening: already listening!" );
+ if ( isControllerListening() )
+ stopControllerListening( );
+ DBG_ASSERT( !isControllerListening(), "FmTextControlShell::startControllerListening: inconsistence!" );
+
+ try
+ {
+ Sequence< Reference< XControl > > aControls( _rxController->getControls() );
+ m_aControlObservers.resize( 0 );
+ m_aControlObservers.reserve( aControls.getLength() );
+
+ const Reference< XControl >* pControls = aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + aControls.getLength();
+ for ( ; pControls != pControlsEnd; ++pControls )
+ {
+ m_aControlObservers.push_back( FocusListenerAdapter( new FmFocusListenerAdapter( *pControls, this ) ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ m_xActiveController = _rxController;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::stopControllerListening( )
+ {
+ OSL_PRECOND( isControllerListening(), "FmTextControlShell::stopControllerListening: inconsistence!" );
+
+ // dispose all listeners associated with the controls of the active controller
+ for ( FocusListenerAdapters::iterator aLoop = m_aControlObservers.begin();
+ aLoop != m_aControlObservers.end();
+ ++aLoop
+ )
+ {
+ (*aLoop)->dispose();
+ }
+
+ FocusListenerAdapters aEmpty;
+ m_aControlObservers.swap( aEmpty );
+
+ m_xActiveController.clear();
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::implClearActiveControlRef()
+ {
+ // no more features for this control
+ for ( ControlFeatures::iterator aLoop = m_aControlFeatures.begin();
+ aLoop != m_aControlFeatures.end();
+ ++aLoop
+ )
+ {
+ aLoop->second->dispose();
+ }
+
+ ControlFeatures aEmpty;
+ m_aControlFeatures.swap( aEmpty );
+
+ if ( m_aContextMenuObserver.get() )
+ {
+ m_aContextMenuObserver->dispose();
+ m_aContextMenuObserver = MouseListenerAdapter();
+ }
+
+ if ( m_xActiveTextComponent.is() )
+ {
+ DBG_TRACE( "FmTextControlShell::ClipBoard: stopping timer for clipboard invalidation" );
+ m_aClipboardInvalidation.Stop();
+ }
+ // no more active control
+ m_xActiveControl.clear();
+ m_xActiveTextComponent.clear();
+ m_bActiveControlIsReadOnly = true;
+ m_bActiveControlIsRichText = false;
+ m_bActiveControl = false;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::controlDeactivated( )
+ {
+ DBG_ASSERT( IsActiveControl(), "FmTextControlShell::controlDeactivated: no active control!" );
+
+ m_bActiveControl = false;
+
+ m_rBindings.Invalidate( pTextControlSlots );
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::controlActivated( const Reference< XControl >& _rxControl )
+ {
+ // ensure that all knittings with the previously active control are lost
+ if ( m_xActiveControl.is() )
+ implClearActiveControlRef();
+ DBG_ASSERT( m_aControlFeatures.empty(), "FmTextControlShell::controlActivated: should have no dispatchers when I'm here!" );
+
+#if OSL_DEBUG_LEVEL > 0
+ {
+ Sequence< Reference< XControl > > aActiveControls;
+ if ( m_xActiveController.is() )
+ aActiveControls = m_xActiveController->getControls();
+
+ bool bFoundThisControl = false;
+
+ const Reference< XControl >* pControls = aActiveControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + aActiveControls.getLength();
+ for ( ; ( pControls != pControlsEnd ) && !bFoundThisControl; ++pControls )
+ {
+ if ( *pControls == _rxControl )
+ bFoundThisControl = true;
+ }
+ DBG_ASSERT( bFoundThisControl, "FmTextControlShell::controlActivated: only controls which belong to the active controller can be activated!" );
+ }
+#endif
+ // ask the control for dispatchers for our text-related slots
+ fillFeatureDispatchers( _rxControl, pTextControlSlots, m_aControlFeatures );
+
+ // remember this control
+ m_xActiveControl = _rxControl;
+ m_xActiveTextComponent = m_xActiveTextComponent.query( _rxControl );
+ m_bActiveControlIsReadOnly = lcl_determineReadOnly( m_xActiveControl );
+ m_bActiveControlIsRichText = lcl_isRichText( m_xActiveControl );
+
+ // if we found a rich text control, we need context menu support
+ if ( m_bActiveControlIsRichText )
+ {
+ DBG_ASSERT( NULL == m_aContextMenuObserver.get(), "FmTextControlShell::controlActivated: already have an observer!" );
+ m_aContextMenuObserver = MouseListenerAdapter( new FmMouseListenerAdapter( _rxControl, this ) );
+ }
+
+ if ( m_xActiveTextComponent.is() )
+ {
+ DBG_TRACE( "FmTextControlShell::ClipBoard: starting timer for clipboard invalidation" );
+ m_aClipboardInvalidation.Start();
+ }
+
+ m_bActiveControl = true;
+
+ m_rBindings.Invalidate( pTextControlSlots );
+
+ if ( m_pViewFrame )
+ m_pViewFrame->UIFeatureChanged();
+
+ // don't call the activation handler if we don't have any slots we can serve
+ // The activation handler is used to put the shell on the top of the dispatcher stack,
+ // so it's preferred when slots are distributed.
+ // Note that this is a slight hack, to prevent that we grab slots from the SfxDispatcher
+ // which should be served by other shells (e.g. Cut/Copy/Paste).
+ // A real solution would be a forwarding-mechanism for slots: We should be on the top
+ // if we're active, but if we cannot handle the slot, then we need to tell the dispatcher
+ // to skip our shell, and pass the slot to the next one. However, this mechanism is not
+ // not in place in SFX.
+ // Another possibility would be to have dedicated shells for the slots which we might
+ // or might not be able to serve. However, this could probably increase the number of
+ // shells too much (In theory, nearly every slot could have an own shell then).
+ //
+ // #i51621# / 2005-08-19 / frank.schoenheit@sun.com
+ bool bHaveAnyServeableSlots = m_xActiveTextComponent.is() || !m_aControlFeatures.empty();
+ if ( m_aControlActivationHandler.IsSet() && bHaveAnyServeableSlots )
+ m_aControlActivationHandler.Call( NULL );
+
+ m_bNeedClipboardInvalidation = true;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::fillFeatureDispatchers( const Reference< XControl > _rxControl, SfxSlotId* _pZeroTerminatedSlots,
+ ControlFeatures& _rDispatchers )
+ {
+ Reference< XDispatchProvider > xProvider( _rxControl, UNO_QUERY );
+ SfxApplication* pApplication = SFX_APP();
+ DBG_ASSERT( pApplication, "FmTextControlShell::fillFeatureDispatchers: no SfxApplication!" );
+ if ( xProvider.is() && pApplication )
+ {
+ SfxSlotId* pSlots = _pZeroTerminatedSlots;
+ while ( *pSlots )
+ {
+ FmTextControlFeature* pDispatcher = implGetFeatureDispatcher( xProvider, pApplication, *pSlots );
+ if ( pDispatcher )
+ _rDispatchers.insert( ControlFeatures::value_type( *pSlots, ControlFeature( pDispatcher ) ) );
+
+ ++pSlots;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::impl_parseURL_nothrow( URL& _rURL )
+ {
+ try
+ {
+ if ( !m_xURLTransformer.is() )
+ {
+ ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
+ aContext.createComponent( "com.sun.star.util.URLTransformer", m_xURLTransformer );
+ }
+ if ( m_xURLTransformer.is() )
+ m_xURLTransformer->parseStrict( _rURL );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ FmTextControlFeature* FmTextControlShell::implGetFeatureDispatcher( const Reference< XDispatchProvider >& _rxProvider, SfxApplication* _pApplication, SfxSlotId _nSlot )
+ {
+ OSL_PRECOND( _rxProvider.is() && _pApplication, "FmTextControlShell::implGetFeatureDispatcher: invalid arg(s)!" );
+ URL aFeatureURL;
+ aFeatureURL.Complete = lcl_getUnoSlotName( *_pApplication, _nSlot );
+ impl_parseURL_nothrow( aFeatureURL );
+ Reference< XDispatch > xDispatcher = _rxProvider->queryDispatch( aFeatureURL, ::rtl::OUString(), 0xFF );
+ if ( xDispatcher.is() )
+ return new FmTextControlFeature( xDispatcher, aFeatureURL, _nSlot, this );
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::Invalidate( SfxSlotId _nSlot )
+ {
+ m_rBindings.Invalidate( _nSlot );
+ // despite this method being called "Invalidate", we also update here - this gives more immediate
+ // feedback in the UI
+ m_rBindings.Update( _nSlot );
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::focusGained( const ::com::sun::star::awt::FocusEvent& _rEvent )
+ {
+ Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
+
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OString sTrace( "FmTextControlShell::focusGained: 0x" );
+ sTrace += ::rtl::OString::valueOf( (sal_IntPtr)xControl.get(), 16 );
+ DBG_TRACE( sTrace );
+#endif
+
+ DBG_ASSERT( xControl.is(), "FmTextControlShell::focusGained: suspicious focus event!" );
+ if ( xControl.is() )
+ controlActivated( xControl );
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::focusLost( const ::com::sun::star::awt::FocusEvent& _rEvent )
+ {
+ Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
+
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OString sTrace( "FmTextControlShell::focusLost: 0x" );
+ sTrace += ::rtl::OString::valueOf( (sal_IntPtr)xControl.get(), 16 );
+ DBG_TRACE( sTrace );
+#endif
+
+ m_bActiveControl = false;
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::ForgetActiveControl()
+ {
+ implClearActiveControlRef();
+ }
+
+ //------------------------------------------------------------------------
+ void FmTextControlShell::contextMenuRequested( const awt::MouseEvent& /*_rEvent*/ )
+ {
+ m_rBindings.GetDispatcher()->ExecutePopup( SVX_RES( RID_FM_TEXTATTRIBUTE_MENU ) );
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmtools.cxx b/svx/source/form/fmtools.cxx
new file mode 100644
index 000000000000..432213384298
--- /dev/null
+++ b/svx/source/form/fmtools.cxx
@@ -0,0 +1,498 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmprop.hrc"
+#include "fmservs.hxx"
+#include "svx/fmtools.hxx"
+#include "svx/dbtoolsclient.hxx"
+#include "svx/fmglob.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/awt/LineEndFormat.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XIntrospection.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/form/XGridColumnFactory.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XObjectInputStream.hpp>
+#include <com/sun/star/io/XObjectOutputStream.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/XResultSetAccess.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/uno/XNamingService.hpp>
+#include <com/sun/star/util/Language.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/XNumberFormats.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+/** === end UNO includes === **/
+
+#include <basic/sbxvar.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <comphelper/container.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/uno3.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+#include <cppuhelper/servicefactory.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <toolkit/unohlp.hxx>
+#include <tools/debug.hxx>
+#include <tools/string.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/svapp.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::form;
+using namespace ::svxform;
+using namespace ::connectivity::simple;
+
+// ------------------------------------------------------------------------------
+namespace
+{
+ static bool lcl_shouldDisplayError( const Any& _rError )
+ {
+ SQLException aError;
+ if ( !( _rError >>= aError ) )
+ return true;
+
+ if ( aError.Message.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "[OOoBase]" ) ) != 0 )
+ // it is an exception *not* thrown by an OOo Base core component
+ return true;
+
+ // the only exception we do not display ATM is a RowSetVetoException, which
+ // has been raised because an XRowSetApprovalListener vetoed a change
+ if ( aError.ErrorCode + ErrorCondition::ROW_SET_OPERATION_VETOED == 0 )
+ return false;
+
+ // everything else is to be displayed
+ return true;
+ }
+}
+
+// ------------------------------------------------------------------------------
+void displayException(const Any& _rExcept, Window* _pParent)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "fmtools::displayException" );
+ // check whether we need to display it
+ if ( !lcl_shouldDisplayError( _rExcept ) )
+ return;
+
+ try
+ {
+ // the parent window
+ Window* pParentWindow = _pParent ? _pParent : GetpApp()->GetDefDialogParent();
+ Reference< XWindow > xParentWindow = VCLUnoHelper::GetInterface(pParentWindow);
+
+ Sequence< Any > aArgs(2);
+ aArgs[0] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SQLException")), 0, _rExcept, PropertyState_DIRECT_VALUE);
+ aArgs[1] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")), 0, makeAny(xParentWindow), PropertyState_DIRECT_VALUE);
+
+ static ::rtl::OUString s_sDialogServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.ErrorMessageDialog") );
+ Reference< XExecutableDialog > xErrorDialog(
+ ::comphelper::getProcessServiceFactory()->createInstanceWithArguments(s_sDialogServiceName, aArgs), UNO_QUERY);
+ if (xErrorDialog.is())
+ xErrorDialog->execute();
+ else
+ ShowServiceNotAvailableError(pParentWindow, s_sDialogServiceName, sal_True);
+ }
+ catch(Exception&)
+ {
+ OSL_ENSURE(sal_False, "displayException: could not display the error message!");
+ }
+}
+
+// ------------------------------------------------------------------------------
+void displayException(const ::com::sun::star::sdbc::SQLException& _rExcept, Window* _pParent)
+{
+ displayException(makeAny(_rExcept), _pParent);
+}
+
+// ------------------------------------------------------------------------------
+void displayException(const ::com::sun::star::sdbc::SQLWarning& _rExcept, Window* _pParent)
+{
+ displayException(makeAny(_rExcept), _pParent);
+}
+
+// ------------------------------------------------------------------------------
+void displayException(const ::com::sun::star::sdb::SQLContext& _rExcept, Window* _pParent)
+{
+ displayException(makeAny(_rExcept), _pParent);
+}
+
+// ------------------------------------------------------------------------------
+void displayException(const ::com::sun::star::sdb::SQLErrorEvent& _rEvent, Window* _pParent)
+{
+ displayException(_rEvent.Reason, _pParent);
+}
+
+//------------------------------------------------------------------------------
+sal_Int32 getElementPos(const Reference< ::com::sun::star::container::XIndexAccess>& xCont, const Reference< XInterface >& xElement)
+{
+ sal_Int32 nIndex = -1;
+ if (!xCont.is())
+ return nIndex;
+
+
+ Reference< XInterface > xNormalized( xElement, UNO_QUERY );
+ DBG_ASSERT( xNormalized.is(), "getElementPos: invalid element!" );
+ if ( xNormalized.is() )
+ {
+ // Feststellen an welcher Position sich das Kind befindet
+ nIndex = xCont->getCount();
+ while (nIndex--)
+ {
+ try
+ {
+ Reference< XInterface > xCurrent(xCont->getByIndex( nIndex ),UNO_QUERY);
+ DBG_ASSERT( xCurrent.get() == Reference< XInterface >( xCurrent, UNO_QUERY ).get(),
+ "getElementPos: container element not normalized!" );
+ if ( xNormalized.get() == xCurrent.get() )
+ break;
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR( "getElementPos: caught an exception!" );
+ }
+
+ }
+ }
+ return nIndex;
+}
+
+//------------------------------------------------------------------
+::rtl::OUString getLabelName(const Reference< ::com::sun::star::beans::XPropertySet>& xControlModel)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "fmtools::getLabelName" );
+ if (!xControlModel.is())
+ return ::rtl::OUString();
+
+ if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xControlModel))
+ {
+ Reference< ::com::sun::star::beans::XPropertySet> xLabelSet;
+ xControlModel->getPropertyValue(FM_PROP_CONTROLLABEL) >>= xLabelSet;
+ if (xLabelSet.is() && ::comphelper::hasProperty(FM_PROP_LABEL, xLabelSet))
+ {
+ Any aLabel( xLabelSet->getPropertyValue(FM_PROP_LABEL) );
+ if ((aLabel.getValueTypeClass() == TypeClass_STRING) && ::comphelper::getString(aLabel).getLength())
+ return ::comphelper::getString(aLabel);
+ }
+ }
+
+ return ::comphelper::getString(xControlModel->getPropertyValue(FM_PROP_CONTROLSOURCE));
+}
+
+//========================================================================
+// = CursorWrapper
+//------------------------------------------------------------------------
+CursorWrapper::CursorWrapper(const Reference< ::com::sun::star::sdbc::XRowSet>& _rxCursor, sal_Bool bUseCloned)
+{
+ ImplConstruct(Reference< ::com::sun::star::sdbc::XResultSet>(_rxCursor, UNO_QUERY), bUseCloned);
+}
+
+//------------------------------------------------------------------------
+CursorWrapper::CursorWrapper(const Reference< ::com::sun::star::sdbc::XResultSet>& _rxCursor, sal_Bool bUseCloned)
+{
+ ImplConstruct(_rxCursor, bUseCloned);
+}
+
+//------------------------------------------------------------------------
+void CursorWrapper::ImplConstruct(const Reference< ::com::sun::star::sdbc::XResultSet>& _rxCursor, sal_Bool bUseCloned)
+{
+ if (bUseCloned)
+ {
+ Reference< ::com::sun::star::sdb::XResultSetAccess> xAccess(_rxCursor, UNO_QUERY);
+ try
+ {
+ m_xMoveOperations = xAccess.is() ? xAccess->createResultSet() : Reference< ::com::sun::star::sdbc::XResultSet>();
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ else
+ m_xMoveOperations = _rxCursor;
+
+ m_xBookmarkOperations = m_xBookmarkOperations.query( m_xMoveOperations );
+ m_xColumnsSupplier = m_xColumnsSupplier.query( m_xMoveOperations );
+ m_xPropertyAccess = m_xPropertyAccess.query( m_xMoveOperations );
+
+ if ( !m_xMoveOperations.is() || !m_xBookmarkOperations.is() || !m_xColumnsSupplier.is() || !m_xPropertyAccess.is() )
+ { // all or nothing !!
+ m_xMoveOperations = NULL;
+ m_xBookmarkOperations = NULL;
+ m_xColumnsSupplier = NULL;
+ }
+ else
+ m_xGeneric = m_xMoveOperations.get();
+}
+
+//------------------------------------------------------------------------
+const CursorWrapper& CursorWrapper::operator=(const Reference< ::com::sun::star::sdbc::XRowSet>& _rxCursor)
+{
+ m_xMoveOperations = Reference< ::com::sun::star::sdbc::XResultSet>(_rxCursor, UNO_QUERY);
+ m_xBookmarkOperations = Reference< ::com::sun::star::sdbcx::XRowLocate>(_rxCursor, UNO_QUERY);
+ m_xColumnsSupplier = Reference< ::com::sun::star::sdbcx::XColumnsSupplier>(_rxCursor, UNO_QUERY);
+ if (!m_xMoveOperations.is() || !m_xBookmarkOperations.is() || !m_xColumnsSupplier.is())
+ { // all or nothing !!
+ m_xMoveOperations = NULL;
+ m_xBookmarkOperations = NULL;
+ m_xColumnsSupplier = NULL;
+ }
+ return *this;
+}
+
+//------------------------------------------------------------------------------
+FmXDisposeListener::~FmXDisposeListener()
+{
+ setAdapter(NULL);
+}
+
+//------------------------------------------------------------------------------
+void FmXDisposeListener::setAdapter(FmXDisposeMultiplexer* pAdapter)
+{
+ if (m_pAdapter)
+ {
+ ::osl::MutexGuard aGuard(m_rMutex);
+ m_pAdapter->release();
+ m_pAdapter = NULL;
+ }
+
+ if (pAdapter)
+ {
+ ::osl::MutexGuard aGuard(m_rMutex);
+ m_pAdapter = pAdapter;
+ m_pAdapter->acquire();
+ }
+}
+
+//==============================================================================
+DBG_NAME(FmXDisposeMultiplexer);
+//------------------------------------------------------------------------------
+FmXDisposeMultiplexer::FmXDisposeMultiplexer(FmXDisposeListener* _pListener, const Reference< ::com::sun::star::lang::XComponent>& _rxObject, sal_Int16 _nId)
+ :m_xObject(_rxObject)
+ ,m_pListener(_pListener)
+ ,m_nId(_nId)
+{
+ DBG_CTOR(FmXDisposeMultiplexer, NULL);
+ m_pListener->setAdapter(this);
+
+ if (m_xObject.is())
+ m_xObject->addEventListener(this);
+}
+
+//------------------------------------------------------------------------------
+FmXDisposeMultiplexer::~FmXDisposeMultiplexer()
+{
+ DBG_DTOR(FmXDisposeMultiplexer, NULL);
+}
+
+// ::com::sun::star::lang::XEventListener
+//------------------------------------------------------------------
+void FmXDisposeMultiplexer::disposing(const ::com::sun::star::lang::EventObject& _Source) throw( RuntimeException )
+{
+ Reference< ::com::sun::star::lang::XEventListener> xPreventDelete(this);
+
+ if (m_pListener)
+ {
+ m_pListener->disposing(_Source, m_nId);
+ m_pListener->setAdapter(NULL);
+ m_pListener = NULL;
+ }
+ m_xObject = NULL;
+}
+
+//------------------------------------------------------------------
+void FmXDisposeMultiplexer::dispose()
+{
+ if (m_xObject.is())
+ {
+ Reference< ::com::sun::star::lang::XEventListener> xPreventDelete(this);
+
+ m_xObject->removeEventListener(this);
+ m_xObject = NULL;
+
+ m_pListener->setAdapter(NULL);
+ m_pListener = NULL;
+ }
+}
+
+//==============================================================================
+//------------------------------------------------------------------------------
+sal_Int16 getControlTypeByObject(const Reference< ::com::sun::star::lang::XServiceInfo>& _rxObject)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "fmtools::getControlTypeByObject" );
+ // ask for the persistent service name
+ Reference< ::com::sun::star::io::XPersistObject> xPersistence(_rxObject, UNO_QUERY);
+ DBG_ASSERT(xPersistence.is(), "::getControlTypeByObject : argument shold be an ::com::sun::star::io::XPersistObject !");
+ if (!xPersistence.is())
+ return OBJ_FM_CONTROL;
+
+ ::rtl::OUString sPersistentServiceName = xPersistence->getServiceName();
+ if (sPersistentServiceName.equals(FM_COMPONENT_EDIT)) // 5.0-Name
+ {
+ // may be a simple edit field or a formatted field, dependent of the supported services
+ if (_rxObject->supportsService(FM_SUN_COMPONENT_FORMATTEDFIELD))
+ return OBJ_FM_FORMATTEDFIELD;
+ return OBJ_FM_EDIT;
+ }
+ if (sPersistentServiceName.equals(FM_COMPONENT_TEXTFIELD))
+ return OBJ_FM_EDIT;
+ if (sPersistentServiceName.equals(FM_COMPONENT_COMMANDBUTTON))
+ return OBJ_FM_BUTTON;
+ if (sPersistentServiceName.equals(FM_COMPONENT_FIXEDTEXT))
+ return OBJ_FM_FIXEDTEXT;
+ if (sPersistentServiceName.equals(FM_COMPONENT_LISTBOX))
+ return OBJ_FM_LISTBOX;
+ if (sPersistentServiceName.equals(FM_COMPONENT_CHECKBOX))
+ return OBJ_FM_CHECKBOX;
+ if (sPersistentServiceName.equals(FM_COMPONENT_RADIOBUTTON))
+ return OBJ_FM_RADIOBUTTON;
+ if (sPersistentServiceName.equals(FM_COMPONENT_GROUPBOX))
+ return OBJ_FM_GROUPBOX;
+ if (sPersistentServiceName.equals(FM_COMPONENT_COMBOBOX))
+ return OBJ_FM_COMBOBOX;
+ if (sPersistentServiceName.equals(FM_COMPONENT_GRID)) // 5.0-Name
+ return OBJ_FM_GRID;
+ if (sPersistentServiceName.equals(FM_COMPONENT_GRIDCONTROL))
+ return OBJ_FM_GRID;
+ if (sPersistentServiceName.equals(FM_COMPONENT_IMAGEBUTTON))
+ return OBJ_FM_IMAGEBUTTON;
+ if (sPersistentServiceName.equals(FM_COMPONENT_FILECONTROL))
+ return OBJ_FM_FILECONTROL;
+ if (sPersistentServiceName.equals(FM_COMPONENT_DATEFIELD))
+ return OBJ_FM_DATEFIELD;
+ if (sPersistentServiceName.equals(FM_COMPONENT_TIMEFIELD))
+ return OBJ_FM_TIMEFIELD;
+ if (sPersistentServiceName.equals(FM_COMPONENT_NUMERICFIELD))
+ return OBJ_FM_NUMERICFIELD;
+ if (sPersistentServiceName.equals(FM_COMPONENT_CURRENCYFIELD))
+ return OBJ_FM_CURRENCYFIELD;
+ if (sPersistentServiceName.equals(FM_COMPONENT_PATTERNFIELD))
+ return OBJ_FM_PATTERNFIELD;
+ if (sPersistentServiceName.equals(FM_COMPONENT_HIDDEN)) // 5.0-Name
+ return OBJ_FM_HIDDEN;
+ if (sPersistentServiceName.equals(FM_COMPONENT_HIDDENCONTROL))
+ return OBJ_FM_HIDDEN;
+ if (sPersistentServiceName.equals(FM_COMPONENT_IMAGECONTROL))
+ return OBJ_FM_IMAGECONTROL;
+ if (sPersistentServiceName.equals(FM_COMPONENT_FORMATTEDFIELD))
+ {
+ DBG_ERROR("::getControlTypeByObject : suspicious persistent service name (formatted field) !");
+ // objects with that service name should exist as they aren't compatible with older versions
+ return OBJ_FM_FORMATTEDFIELD;
+ }
+ if ( sPersistentServiceName.equals( FM_SUN_COMPONENT_SCROLLBAR ) )
+ return OBJ_FM_SCROLLBAR;
+ if ( sPersistentServiceName.equals( FM_SUN_COMPONENT_SPINBUTTON) )
+ return OBJ_FM_SPINBUTTON;
+ if (sPersistentServiceName.equals(FM_SUN_COMPONENT_NAVIGATIONBAR))
+ return OBJ_FM_NAVIGATIONBAR;
+
+ DBG_ERROR("::getControlTypeByObject : unknown object type !");
+ return OBJ_FM_CONTROL;
+}
+
+//------------------------------------------------------------------------------
+void setConnection(const Reference< ::com::sun::star::sdbc::XRowSet>& _rxRowSet, const Reference< ::com::sun::star::sdbc::XConnection>& _rxConn)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "fmtools::setConnection" );
+ Reference< ::com::sun::star::beans::XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY);
+ if (xRowSetProps.is())
+ {
+ try
+ {
+ Any aConn(makeAny(_rxConn));
+ xRowSetProps->setPropertyValue(FM_PROP_ACTIVE_CONNECTION, aConn);
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("::setConnection : could not set the connection !");
+ }
+
+ }
+}
+//------------------------------------------------------------------------------
+sal_Bool isRowSetAlive(const Reference< XInterface >& _rxRowSet)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "fmtools::isRowSetAlive" );
+ sal_Bool bIsAlive = sal_False;
+ Reference< ::com::sun::star::sdbcx::XColumnsSupplier> xSupplyCols(_rxRowSet, UNO_QUERY);
+ Reference< ::com::sun::star::container::XIndexAccess> xCols;
+ if (xSupplyCols.is())
+ xCols = Reference< ::com::sun::star::container::XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
+ if (xCols.is() && (xCols->getCount() > 0))
+ bIsAlive = sal_True;
+
+ return bIsAlive;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmundo.cxx b/svx/source/form/fmundo.cxx
new file mode 100644
index 000000000000..7dfbea35000b
--- /dev/null
+++ b/svx/source/form/fmundo.cxx
@@ -0,0 +1,1350 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+#include "fmundo.hxx"
+#include "fmpgeimp.hxx"
+#include "svx/dbtoolsclient.hxx"
+#include "svditer.hxx"
+#include "fmobj.hxx"
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+#include "svx/fmglob.hxx"
+#include "svx/dialmgr.hxx"
+#include "svx/fmmodel.hxx"
+#include "svx/fmpage.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/form/binding/XBindableValue.hpp>
+#include <com/sun/star/form/binding/XListEntrySink.hpp>
+#include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
+/** === end UNO includes === **/
+
+#include "svx/fmtools.hxx"
+#include <rtl/logfile.hxx>
+#include <svl/macitem.hxx>
+#include <tools/shl.hxx>
+#include <tools/diagnose_ex.h>
+#include <sfx2/objsh.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/sfx.hrc>
+#include <sfx2/event.hxx>
+#include <osl/mutex.hxx>
+#include <osl/mutex.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/stl_types.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::reflection;
+using namespace ::com::sun::star::form::binding;
+using namespace ::svxform;
+
+
+#include <com/sun/star/script/XScriptListener.hdl>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+typedef cppu::WeakImplHelper1< XScriptListener > ScriptEventListener_BASE;
+class ScriptEventListenerWrapper : public ScriptEventListener_BASE
+{
+public:
+ ScriptEventListenerWrapper( FmFormModel& _rModel) throw ( RuntimeException ) : pModel(&_rModel)
+ {
+
+ }
+ // XEventListener
+ virtual void SAL_CALL disposing(const EventObject& ) throw( RuntimeException ){}
+
+ // XScriptListener
+ virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException)
+ {
+ setModel();
+ if ( m_vbaListener.is() )
+ {
+ m_vbaListener->firing( evt );
+ }
+ }
+
+ virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw( com::sun::star::reflection::InvocationTargetException, RuntimeException)
+ {
+ setModel();
+ if ( m_vbaListener.is() )
+ {
+ return m_vbaListener->approveFiring( evt );
+ }
+ return Any();
+ }
+
+private:
+ void setModel()
+ {
+ if ( !m_vbaListener.is() )
+ {
+ Reference < XPropertySet > xProps(
+ ::comphelper::getProcessServiceFactory(), UNO_QUERY );
+ if ( xProps.is() )
+ {
+ Reference< XComponentContext > xCtx( xProps->getPropertyValue(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY );
+ if ( xCtx.is() )
+ {
+ Reference< XMultiComponentFactory > xMFac(
+ xCtx->getServiceManager(), UNO_QUERY );
+ SfxObjectShellRef xObjSh = pModel->GetObjectShell();
+ Reference< XMultiServiceFactory > xDocFac;
+ if ( xObjSh.Is() )
+ xDocFac.set( xObjSh->GetModel(), UNO_QUERY );
+
+ if ( xMFac.is() )
+ {
+ m_vbaListener.set( xMFac->createInstanceWithContext(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "ooo.vba.EventListener" ) ), xCtx ),
+ UNO_QUERY_THROW );
+ }
+ }
+ }
+ }
+ Reference< XPropertySet > xProps( m_vbaListener, UNO_QUERY );
+ if ( xProps.is() )
+ {
+ try
+ {
+ SfxObjectShellRef xObjSh = pModel->GetObjectShell();
+ if ( xObjSh.Is() && m_vbaListener.is() )
+ {
+ Any aVal;
+ aVal <<= xObjSh->GetModel();
+ xProps->setPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) ),
+ aVal );
+ }
+ }
+ catch( Exception& )
+ {
+ //swallow any errors
+ }
+ }
+ }
+ FmFormModel* pModel;
+ Reference< XScriptListener > m_vbaListener;
+
+
+};
+
+//------------------------------------------------------------------------------
+// some helper structs for caching property infos
+//------------------------------------------------------------------------------
+struct PropertyInfo
+{
+ BOOL bIsTransientOrReadOnly : 1; // the property is transient or read-only, thus we need no undo action for it
+ BOOL bIsValueProperty : 1; // the property is the special value property, thus it may be handled
+ // as if it's transient or persistent
+};
+
+struct PropertySetInfo
+{
+ DECLARE_STL_USTRINGACCESS_MAP(PropertyInfo, AllProperties);
+
+ AllProperties aProps; // all properties of this set which we know so far
+ BOOL bHasEmptyControlSource; // sal_True -> the set has a DataField property, and the current value is an empty string
+ // sal_False -> the set has _no_ such property or it's value isn't empty
+};
+
+BOOL operator < (const Reference< XPropertySet >& lhs,
+ const Reference< XPropertySet >& rhs)
+{
+ return lhs.get() < rhs.get();
+}
+
+DECLARE_STL_STDKEY_MAP(Reference< XPropertySet >, PropertySetInfo, PropertySetInfoCache);
+
+//------------------------------------------------------------------------------
+
+String static_STR_UNDO_PROPERTY;
+//------------------------------------------------------------------------------
+DBG_NAME(FmXUndoEnvironment)
+//------------------------------------------------------------------------------
+FmXUndoEnvironment::FmXUndoEnvironment(FmFormModel& _rModel)
+ :rModel( _rModel )
+ ,m_pPropertySetCache( NULL )
+ ,m_pScriptingEnv( ::svxform::createDefaultFormScriptingEnvironment( _rModel ) )
+ ,m_Locks( 0 )
+ ,bReadOnly( sal_False )
+ ,m_bDisposed( false )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::FmXUndoEnvironment" );
+ DBG_CTOR(FmXUndoEnvironment,NULL);
+ try
+ {
+ m_vbaListener = new ScriptEventListenerWrapper( _rModel );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+//------------------------------------------------------------------------------
+FmXUndoEnvironment::~FmXUndoEnvironment()
+{
+ DBG_DTOR(FmXUndoEnvironment,NULL);
+ if (m_pPropertySetCache)
+ delete static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::dispose()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::dispose" );
+ OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::dispose: disposed twice?" );
+ if ( !m_bDisposed )
+ return;
+
+ Lock();
+
+ sal_uInt16 nCount = rModel.GetPageCount();
+ sal_uInt16 i;
+ for (i = 0; i < nCount; i++)
+ {
+ FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
+ if ( pPage )
+ {
+ Reference< XInterface > xForms = pPage->GetForms( false ).get();
+ if ( xForms.is() )
+ RemoveElement( xForms );
+ }
+ }
+
+ nCount = rModel.GetMasterPageCount();
+ for (i = 0; i < nCount; i++)
+ {
+ FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
+ if ( pPage )
+ {
+ Reference< XInterface > xForms = pPage->GetForms( false ).get();
+ if ( xForms.is() )
+ RemoveElement( xForms );
+ }
+ }
+
+ UnLock();
+
+ OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::dispose: no object shell anymore!" );
+ if ( rModel.GetObjectShell() )
+ EndListening( *rModel.GetObjectShell() );
+
+ if ( IsListening( rModel ) )
+ EndListening( rModel );
+
+ m_pScriptingEnv->dispose();
+
+ m_bDisposed = true;
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::ModeChanged()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::ModeChanged" );
+ OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::ModeChanged: no object shell anymore!" );
+ if ( !rModel.GetObjectShell() )
+ return;
+
+ if (bReadOnly != (rModel.GetObjectShell()->IsReadOnly() || rModel.GetObjectShell()->IsReadOnlyUI()))
+ {
+ bReadOnly = !bReadOnly;
+
+ sal_uInt16 nCount = rModel.GetPageCount();
+ sal_uInt16 i;
+ for (i = 0; i < nCount; i++)
+ {
+ FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
+ if ( pPage )
+ {
+ Reference< XInterface > xForms = pPage->GetForms( false ).get();
+ if ( xForms.is() )
+ TogglePropertyListening( xForms );
+ }
+ }
+
+ nCount = rModel.GetMasterPageCount();
+ for (i = 0; i < nCount; i++)
+ {
+ FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
+ if ( pPage )
+ {
+ Reference< XInterface > xForms = pPage->GetForms( false ).get();
+ if ( xForms.is() )
+ TogglePropertyListening( xForms );
+ }
+ }
+
+ if (!bReadOnly)
+ StartListening(rModel);
+ else
+ EndListening(rModel);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Notify" );
+ if (rHint.ISA(SdrHint))
+ {
+ SdrHint* pSdrHint = (SdrHint*)&rHint;
+ switch( pSdrHint->GetKind() )
+ {
+ case HINT_OBJINSERTED:
+ {
+ SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
+ Inserted( pSdrObj );
+ } break;
+ case HINT_OBJREMOVED:
+ {
+ SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
+ Removed( pSdrObj );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if (rHint.ISA(SfxSimpleHint))
+ {
+ switch ( ((SfxSimpleHint&)rHint).GetId() )
+ {
+ case SFX_HINT_DYING:
+ dispose();
+ rModel.SetObjectShell( NULL );
+ break;
+ case SFX_HINT_MODECHANGED:
+ ModeChanged();
+ break;
+ }
+ }
+ else if (rHint.ISA(SfxEventHint))
+ {
+ switch (((SfxEventHint&)rHint).GetEventId())
+ {
+ case SFX_EVENT_CREATEDOC:
+ case SFX_EVENT_OPENDOC:
+ ModeChanged();
+ break;
+ }
+ }
+
+}
+
+//------------------------------------------------------------------
+void FmXUndoEnvironment::Inserted(SdrObject* pObj)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
+ if (pObj->GetObjInventor() == FmFormInventor)
+ {
+ FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
+ Inserted( pFormObj );
+ }
+ else if (pObj->IsGroupObject())
+ {
+ SdrObjListIter aIter(*pObj->GetSubList());
+ while ( aIter.IsMore() )
+ Inserted( aIter.Next() );
+ }
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ sal_Bool lcl_searchElement(const Reference< XIndexAccess>& xCont, const Reference< XInterface >& xElement)
+ {
+ if (!xCont.is() || !xElement.is())
+ return sal_False;
+
+ sal_Int32 nCount = xCont->getCount();
+ Reference< XInterface > xComp;
+ for (sal_Int32 i = 0; i < nCount; i++)
+ {
+ try
+ {
+ xCont->getByIndex(i) >>= xComp;
+ if (xComp.is())
+ {
+ if ( xElement == xComp )
+ return sal_True;
+ else
+ {
+ Reference< XIndexAccess> xCont2(xComp, UNO_QUERY);
+ if (xCont2.is() && lcl_searchElement(xCont2, xElement))
+ return sal_True;
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ return sal_False;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::Inserted(FmFormObj* pObj)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
+ DBG_ASSERT( pObj, "FmXUndoEnvironment::Inserted: invalid object!" );
+ if ( !pObj )
+ return;
+
+ // ist das Control noch einer Form zugeordnet
+ Reference< XInterface > xModel(pObj->GetUnoControlModel(), UNO_QUERY);
+ Reference< XFormComponent > xContent(xModel, UNO_QUERY);
+ if (xContent.is() && pObj->GetPage())
+ {
+ // if the component doesn't belong to a form, yet, find one to insert into
+ if (!xContent->getParent().is())
+ {
+ try
+ {
+ Reference< XIndexContainer > xObjectParent = pObj->GetOriginalParent();
+
+ FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pObj->GetPage() );
+ Reference< XIndexAccess > xForms( rPage.GetForms(), UNO_QUERY_THROW );
+
+ Reference< XIndexContainer > xNewParent;
+ Reference< XForm > xForm;
+ sal_Int32 nPos = -1;
+ if ( lcl_searchElement( xForms, xObjectParent ) )
+ {
+ // the form which was the parent of the object when it was removed is still
+ // part of the form component hierachy of the current page
+ xNewParent = xObjectParent;
+ xForm.set( xNewParent, UNO_QUERY_THROW );
+ nPos = ::std::min( pObj->GetOriginalIndex(), xNewParent->getCount() );
+ }
+ else
+ {
+ xForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
+ xNewParent.set( xForm, UNO_QUERY_THROW );
+ nPos = xNewParent->getCount();
+ }
+
+ rPage.GetImpl().setUniqueName( xContent, xForm );
+ xNewParent->insertByIndex( nPos, makeAny( xContent ) );
+
+ Reference< XEventAttacherManager > xManager( xNewParent, UNO_QUERY_THROW );
+ xManager->registerScriptEvents( nPos, pObj->GetOriginalEvents() );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ // FormObject zuruecksetzen
+ pObj->ClearObjEnv();
+ }
+}
+
+//------------------------------------------------------------------
+void FmXUndoEnvironment::Removed(SdrObject* pObj)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
+ if ( pObj->IsVirtualObj() )
+ // for virtual objects, we've already been notified of the removal of the master
+ // object, which is sufficient here
+ return;
+
+ if (pObj->GetObjInventor() == FmFormInventor)
+ {
+ FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
+ Removed(pFormObj);
+ }
+ else if (pObj->IsGroupObject())
+ {
+ SdrObjListIter aIter(*pObj->GetSubList());
+ while ( aIter.IsMore() )
+ Removed( aIter.Next() );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::Removed(FmFormObj* pObj)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
+ DBG_ASSERT( pObj, "FmXUndoEnvironment::Removed: invalid object!" );
+ if ( !pObj )
+ return;
+
+ // ist das Control noch einer Form zugeordnet
+ Reference< XFormComponent > xContent(pObj->GetUnoControlModel(), UNO_QUERY);
+ if (xContent.is())
+ {
+ // das Object wird aus einer Liste herausgenommen
+ // existiert ein Vater wird das Object beim beim Vater entfernt und
+ // am FormObject gemerkt!
+
+ // wird das Object wieder eingefuegt und ein Parent existiert, so wird dieser
+ // Parent wiederum gesetzt
+ Reference< XIndexContainer > xForm(xContent->getParent(), UNO_QUERY);
+ if (xForm.is())
+ {
+ Reference< XIndexAccess > xIndexAccess((XIndexContainer*)xForm.get());
+ // Feststellen an welcher Position sich das Kind befunden hat
+ const sal_Int32 nPos = getElementPos(xIndexAccess, xContent);
+ if (nPos >= 0)
+ {
+ Sequence< ScriptEventDescriptor > aEvts;
+ Reference< XEventAttacherManager > xManager(xForm, UNO_QUERY);
+ if (xManager.is())
+ aEvts = xManager->getScriptEvents(nPos);
+
+ try
+ {
+ pObj->SetObjEnv(xForm, nPos, aEvts);
+ xForm->removeByIndex(nPos);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ }
+ }
+ }
+}
+
+// XEventListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::disposing(const EventObject& e) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::disposing" );
+ // check if it's an object we have cached informations about
+ if (m_pPropertySetCache)
+ {
+ Reference< XPropertySet > xSourceSet(e.Source, UNO_QUERY);
+ if (xSourceSet.is())
+ {
+ PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
+ PropertySetInfoCacheIterator aSetPos = pCache->find(xSourceSet);
+ if (aSetPos != pCache->end())
+ pCache->erase(aSetPos);
+ }
+ }
+}
+
+// XPropertyChangeListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::propertyChange" );
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ if (!IsLocked())
+ {
+ Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
+ if (!xSet.is())
+ return;
+
+ // if it's a "default value" property of a control model, set the according "value" property
+ static ::rtl::OUString pDefaultValueProperties[] = {
+ FM_PROP_DEFAULT_TEXT, FM_PROP_DEFAULTCHECKED, FM_PROP_DEFAULT_DATE, FM_PROP_DEFAULT_TIME,
+ FM_PROP_DEFAULT_VALUE, FM_PROP_DEFAULT_SELECT_SEQ, FM_PROP_EFFECTIVE_DEFAULT
+ };
+ const ::rtl::OUString aValueProperties[] = {
+ FM_PROP_TEXT, FM_PROP_STATE, FM_PROP_DATE, FM_PROP_TIME,
+ FM_PROP_VALUE, FM_PROP_SELECT_SEQ, FM_PROP_EFFECTIVE_VALUE
+ };
+ sal_Int32 nDefaultValueProps = SAL_N_ELEMENTS(pDefaultValueProperties);
+ OSL_ENSURE(SAL_N_ELEMENTS(aValueProperties) == nDefaultValueProps,
+ "FmXUndoEnvironment::propertyChange: inconsistence!");
+ for (sal_Int32 i=0; i<nDefaultValueProps; ++i)
+ {
+ if (0 == evt.PropertyName.compareTo(pDefaultValueProperties[i]))
+ {
+ try
+ {
+ xSet->setPropertyValue(aValueProperties[i], evt.NewValue);
+ }
+ catch(const Exception&)
+ {
+ OSL_ENSURE(sal_False, "FmXUndoEnvironment::propertyChange: could not adjust the value property!");
+ }
+ }
+ }
+
+ // no Undo for transient and readonly props. But unfortunately "transient" is not only that the
+ // "transient" flag is set for the property in question, instead is is somewhat more complex
+ // Transience criterions are:
+ // - the "transient" flag is set for the property
+ // - OR the control has a non-empty COntrolSource property, i.e. is intended to be bound
+ // to a database column. Note that it doesn't matter here whether the control actually
+ // *is* bound to a column
+ // - OR the control is bound to an external value via XBindableValue/XValueBinding
+ // which does not have a "ExternalData" property being <TRUE/>
+
+ if (!m_pPropertySetCache)
+ m_pPropertySetCache = new PropertySetInfoCache;
+ PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
+
+ // let's see if we know something about the set
+ PropertySetInfoCacheIterator aSetPos = pCache->find(xSet);
+ if (aSetPos == pCache->end())
+ {
+ PropertySetInfo aNewEntry;
+ if (!::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xSet))
+ {
+ aNewEntry.bHasEmptyControlSource = sal_False;
+ }
+ else
+ {
+ try
+ {
+ Any aCurrentControlSource = xSet->getPropertyValue(FM_PROP_CONTROLSOURCE);
+ aNewEntry.bHasEmptyControlSource = !aCurrentControlSource.hasValue() || (::comphelper::getString(aCurrentControlSource).getLength() == 0);
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ aSetPos = pCache->insert(PropertySetInfoCache::value_type(xSet,aNewEntry)).first;
+ DBG_ASSERT(aSetPos != pCache->end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
+ }
+ else
+ { // is it the DataField property ?
+ if (evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
+ {
+ aSetPos->second.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
+ }
+ }
+
+ // now we have access to the cached info about the set
+ // let's see what we know about the property
+ PropertySetInfo::AllProperties& rPropInfos = aSetPos->second.aProps;
+ PropertySetInfo::AllPropertiesIterator aPropertyPos = rPropInfos.find(evt.PropertyName);
+ if (aPropertyPos == rPropInfos.end())
+ { // nothing 'til now ... have to change this ....
+ PropertyInfo aNewEntry;
+
+ // the attributes
+ INT32 nAttributes = xSet->getPropertySetInfo()->getPropertyByName(evt.PropertyName).Attributes;
+ aNewEntry.bIsTransientOrReadOnly = ((nAttributes & PropertyAttribute::READONLY) != 0) || ((nAttributes & PropertyAttribute::TRANSIENT) != 0);
+
+ // check if it is the special "DataFieldProperty"
+ aNewEntry.bIsValueProperty = sal_False;
+ try
+ {
+ if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCEPROPERTY, xSet))
+ {
+ Any aControlSourceProperty = xSet->getPropertyValue(FM_PROP_CONTROLSOURCEPROPERTY);
+ ::rtl::OUString sControlSourceProperty;
+ aControlSourceProperty >>= sControlSourceProperty;
+
+ aNewEntry.bIsValueProperty = (sControlSourceProperty.equals(evt.PropertyName));
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // insert the new entry
+ aPropertyPos = rPropInfos.insert(PropertySetInfo::AllProperties::value_type(evt.PropertyName,aNewEntry)).first;
+ DBG_ASSERT(aPropertyPos != rPropInfos.end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
+ }
+
+ // now we have access to the cached info about the property affected
+ // and are able to decide wether or not we need an undo action
+
+ bool bAddUndoAction = rModel.IsUndoEnabled();
+ // no UNDO for transient/readonly properties
+ if ( bAddUndoAction && aPropertyPos->second.bIsTransientOrReadOnly )
+ bAddUndoAction = false;
+
+ if ( bAddUndoAction && aPropertyPos->second.bIsValueProperty )
+ {
+ // no UNDO when the "value" property changes, but the ControlSource is non-empty
+ // (in this case the control is intended to be bound to a database column)
+ if ( !aSetPos->second.bHasEmptyControlSource )
+ bAddUndoAction = false;
+
+ // no UNDO if the control is currently bound to an external value
+ if ( bAddUndoAction )
+ {
+ Reference< XBindableValue > xBindable( evt.Source, UNO_QUERY );
+ Reference< XValueBinding > xBinding;
+ if ( xBindable.is() )
+ xBinding = xBindable->getValueBinding();
+
+ Reference< XPropertySet > xBindingProps;
+ Reference< XPropertySetInfo > xBindingPropsPSI;
+ if ( xBindable.is() )
+ xBindingProps.set( xBinding, UNO_QUERY );
+ if ( xBindingProps.is() )
+ xBindingPropsPSI = xBindingProps->getPropertySetInfo();
+ // TODO: we should cache all those things, else this might be too expensive.
+ // However, this requires we're notified of changes in the value binding
+
+ static const ::rtl::OUString s_sExternalData( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) );
+ if ( xBindingPropsPSI.is() && xBindingPropsPSI->hasPropertyByName( s_sExternalData ) )
+ {
+ sal_Bool bExternalData = sal_True;
+ OSL_VERIFY( xBindingProps->getPropertyValue( s_sExternalData ) >>= bExternalData );
+ bAddUndoAction = !bExternalData;
+ }
+ else
+ bAddUndoAction = !xBinding.is();
+ }
+ }
+
+ if ( bAddUndoAction && ( evt.PropertyName == FM_PROP_STRINGITEMLIST ) )
+ {
+ Reference< XListEntrySink > xSink( evt.Source, UNO_QUERY );
+ if ( xSink.is() && xSink->getListEntrySource().is() )
+ // #i41029# / 2005-01-31 / frank.schoenheit@sun.com
+ bAddUndoAction = false;
+ }
+
+ if ( bAddUndoAction )
+ {
+ aGuard.clear();
+ // TODO: this is a potential race condition: two threads here could in theory
+ // add their undo actions out-of-order
+
+ SolarMutexGuard aSolarGuard;
+ rModel.AddUndo(new FmUndoPropertyAction(rModel, evt));
+ }
+ }
+ else
+ {
+ // if it's the DataField property we may have to adjust our cache
+ if (m_pPropertySetCache && evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
+ {
+ Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
+ PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
+ PropertySetInfo& rSetInfo = (*pCache)[xSet];
+ rSetInfo.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
+ }
+ }
+}
+
+// XContainerListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementInserted" );
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // neues Object zum lauschen
+ Reference< XInterface > xIface;
+ evt.Element >>= xIface;
+ OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementInserted: invalid container notification!");
+ AddElement(xIface);
+
+ implSetModified();
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::implSetModified()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::implSetModified" );
+ if ( !IsLocked() && rModel.GetObjectShell() )
+ {
+ rModel.GetObjectShell()->SetModified( sal_True );
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementReplaced" );
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XInterface > xIface;
+ evt.ReplacedElement >>= xIface;
+ OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementReplaced: invalid container notification!");
+ RemoveElement(xIface);
+
+ evt.Element >>= xIface;
+ AddElement(xIface);
+
+ implSetModified();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementRemoved" );
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XInterface > xIface( evt.Element, UNO_QUERY );
+ OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementRemoved: invalid container notification!");
+ RemoveElement(xIface);
+
+ implSetModified();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXUndoEnvironment::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::modified" );
+ implSetModified();
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::AddForms(const Reference< XNameContainer > & rForms)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddForms" );
+ Lock();
+ Reference< XInterface > xInt(rForms, UNO_QUERY);
+ AddElement(xInt);
+ UnLock();
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::RemoveForms(const Reference< XNameContainer > & rForms)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveForms" );
+ Lock();
+ Reference< XInterface > xInt(rForms, UNO_QUERY);
+ RemoveElement(xInt);
+ UnLock();
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::TogglePropertyListening(const Reference< XInterface > & Element)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::TogglePropertyListening" );
+ // am Container horchen
+ Reference< XIndexContainer > xContainer(Element, UNO_QUERY);
+ if (xContainer.is())
+ {
+ sal_uInt32 nCount = xContainer->getCount();
+ Reference< XInterface > xIface;
+ for (sal_uInt32 i = 0; i < nCount; i++)
+ {
+ xContainer->getByIndex(i) >>= xIface;
+ TogglePropertyListening(xIface);
+ }
+ }
+
+ Reference< XPropertySet > xSet(Element, UNO_QUERY);
+ if (xSet.is())
+ {
+ if (!bReadOnly)
+ xSet->addPropertyChangeListener( ::rtl::OUString(), this );
+ else
+ xSet->removePropertyChangeListener( ::rtl::OUString(), this );
+ }
+}
+
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::switchListening( const Reference< XIndexContainer >& _rxContainer, bool _bStartListening ) SAL_THROW(())
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
+ OSL_PRECOND( _rxContainer.is(), "FmXUndoEnvironment::switchListening: invalid container!" );
+ if ( !_rxContainer.is() )
+ return;
+
+ try
+ {
+ // if it's an EventAttacherManager, then we need to listen for
+ // script events
+ Reference< XEventAttacherManager > xManager( _rxContainer, UNO_QUERY );
+ if ( xManager.is() )
+ {
+ if ( _bStartListening )
+ {
+ m_pScriptingEnv->registerEventAttacherManager( xManager );
+ if ( m_vbaListener.is() )
+ xManager->addScriptListener( m_vbaListener );
+ }
+ else
+ {
+ m_pScriptingEnv->revokeEventAttacherManager( xManager );
+ if ( m_vbaListener.is() )
+ xManager->removeScriptListener( m_vbaListener );
+ }
+ }
+
+ // also handle all children of this element
+ sal_uInt32 nCount = _rxContainer->getCount();
+ Reference< XInterface > xInterface;
+ for ( sal_uInt32 i = 0; i < nCount; ++i )
+ {
+ _rxContainer->getByIndex( i ) >>= xInterface;
+ if ( _bStartListening )
+ AddElement( xInterface );
+ else
+ RemoveElement( xInterface );
+ }
+
+ // be notified of any changes in the container elements
+ Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
+ OSL_ENSURE( xSimpleContainer.is(), "FmXUndoEnvironment::switchListening: how are we expected to be notified of changes in the container?" );
+ if ( xSimpleContainer.is() )
+ {
+ if ( _bStartListening )
+ xSimpleContainer->addContainerListener( this );
+ else
+ xSimpleContainer->removeContainerListener( this );
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::switchListening( const Reference< XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
+ OSL_PRECOND( _rxObject.is(), "FmXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
+
+ try
+ {
+ if ( !bReadOnly )
+ {
+ Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
+ if ( xProps.is() )
+ {
+ if ( _bStartListening )
+ xProps->addPropertyChangeListener( ::rtl::OUString(), this );
+ else
+ xProps->removePropertyChangeListener( ::rtl::OUString(), this );
+ }
+ }
+
+ Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
+ if ( xBroadcaster.is() )
+ {
+ if ( _bStartListening )
+ xBroadcaster->addModifyListener( this );
+ else
+ xBroadcaster->removeModifyListener( this );
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::AddElement(const Reference< XInterface >& _rxElement )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddElement" );
+ OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::AddElement: not when I'm already disposed!" );
+
+ // am Container horchen
+ Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
+ if ( xContainer.is() )
+ switchListening( xContainer, true );
+
+ switchListening( _rxElement, true );
+}
+
+//------------------------------------------------------------------------------
+void FmXUndoEnvironment::RemoveElement(const Reference< XInterface >& _rxElement)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveElement" );
+ if ( m_bDisposed )
+ return;
+
+ switchListening( _rxElement, false );
+
+ if (!bReadOnly)
+ {
+ // reset the ActiveConnection if the form is to be removed. This will (should) free the resources
+ // associated with this connection
+ // 86299 - 05/02/2001 - frank.schoenheit@germany.sun.com
+ Reference< XForm > xForm( _rxElement, UNO_QUERY );
+ Reference< XPropertySet > xFormProperties( xForm, UNO_QUERY );
+ if ( xFormProperties.is() )
+ if ( !::svxform::OStaticDataAccessTools().isEmbeddedInDatabase( _rxElement ) )
+ // (if there is a connection in the context of the component, setting
+ // a new connection would be vetoed, anyway)
+ // #i34196# - 2004-09-21 - fs@openoffice.org
+ xFormProperties->setPropertyValue( FM_PROP_ACTIVE_CONNECTION, Any() );
+ }
+
+ Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
+ if ( xContainer.is() )
+ switchListening( xContainer, false );
+}
+
+
+//------------------------------------------------------------------------------
+FmUndoPropertyAction::FmUndoPropertyAction(FmFormModel& rNewMod, const PropertyChangeEvent& evt)
+ :SdrUndoAction(rNewMod)
+ ,xObj(evt.Source, UNO_QUERY)
+ ,aPropertyName(evt.PropertyName)
+ ,aNewValue(evt.NewValue)
+ ,aOldValue(evt.OldValue)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::FmUndoPropertyAction" );
+ if (rNewMod.GetObjectShell())
+ rNewMod.GetObjectShell()->SetModified(sal_True);
+ if(static_STR_UNDO_PROPERTY.Len() == 0)
+ static_STR_UNDO_PROPERTY = SVX_RES(RID_STR_UNDO_PROPERTY);
+}
+
+
+//------------------------------------------------------------------------------
+void FmUndoPropertyAction::Undo()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Undo" );
+ FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
+
+ if (xObj.is() && !rEnv.IsLocked())
+ {
+ rEnv.Lock();
+ try
+ {
+ xObj->setPropertyValue( aPropertyName, aOldValue );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmUndoPropertyAction::Undo: caught an exception!" );
+ }
+ rEnv.UnLock();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoPropertyAction::Redo()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Redo" );
+ FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
+
+ if (xObj.is() && !rEnv.IsLocked())
+ {
+ rEnv.Lock();
+ try
+ {
+ xObj->setPropertyValue( aPropertyName, aNewValue );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmUndoPropertyAction::Redo: caught an exception!" );
+ }
+ rEnv.UnLock();
+ }
+}
+
+//------------------------------------------------------------------------------
+String FmUndoPropertyAction::GetComment() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::GetComment" );
+ String aStr(static_STR_UNDO_PROPERTY);
+
+ aStr.SearchAndReplace( '#', aPropertyName );
+ return aStr;
+}
+
+
+DBG_NAME(FmUndoContainerAction);
+//------------------------------------------------------------------------------
+FmUndoContainerAction::FmUndoContainerAction(FmFormModel& _rMod,
+ Action _eAction,
+ const Reference< XIndexContainer > & xCont,
+ const Reference< XInterface > & xElem,
+ sal_Int32 nIdx)
+ :SdrUndoAction( _rMod )
+ ,m_xContainer( xCont )
+ ,m_nIndex( nIdx )
+ ,m_eAction( _eAction )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::FmUndoContainerAction" );
+ OSL_ENSURE( nIdx >= 0, "FmUndoContainerAction::FmUndoContainerAction: invalid index!" );
+ // some old code suggested this could be a valid argument. However, this code was
+ // buggy, and it *seemed* that nobody used it - so it was removed.
+
+ DBG_CTOR(FmUndoContainerAction,NULL);
+ if ( xCont.is() && xElem.is() )
+ {
+ // normalize
+ m_xElement = m_xElement.query( xElem );
+ if ( m_eAction == Removed )
+ {
+ if (m_nIndex >= 0)
+ {
+ Reference< XEventAttacherManager > xManager( xCont, UNO_QUERY );
+ if ( xManager.is() )
+ m_aEvents = xManager->getScriptEvents(m_nIndex);
+ }
+ else
+ m_xElement = NULL;
+
+ // we now own the element
+ m_xOwnElement = m_xElement;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+FmUndoContainerAction::~FmUndoContainerAction()
+{
+ // if we own the object ....
+ DisposeElement( m_xOwnElement );
+ DBG_DTOR(FmUndoContainerAction,NULL);
+}
+
+//------------------------------------------------------------------------------
+
+void FmUndoContainerAction::DisposeElement( const Reference< XInterface > & xElem )
+{
+ Reference< XComponent > xComp( xElem, UNO_QUERY );
+ if ( xComp.is() )
+ {
+ // and the object does not have a parent
+ Reference< XChild > xChild( xElem, UNO_QUERY );
+ if ( xChild.is() && !xChild->getParent().is() )
+ // -> dispose it
+ xComp->dispose();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoContainerAction::implReInsert( ) SAL_THROW( ( Exception ) )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReInsert" );
+ if ( m_xContainer->getCount() >= m_nIndex )
+ {
+ // insert the element
+ Any aVal;
+ if ( m_xContainer->getElementType() == ::getCppuType( static_cast< const Reference< XFormComponent >* >( NULL ) ) )
+ {
+ aVal <<= Reference< XFormComponent >( m_xElement, UNO_QUERY );
+ }
+ else
+ {
+ aVal <<= Reference< XForm >( m_xElement, UNO_QUERY );
+ }
+ m_xContainer->insertByIndex( m_nIndex, aVal );
+
+ OSL_ENSURE( getElementPos( m_xContainer.get(), m_xElement ) == m_nIndex, "FmUndoContainerAction::implReInsert: insertion did not work!" );
+
+ // register the events
+ Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
+ if ( xManager.is() )
+ xManager->registerScriptEvents( m_nIndex, m_aEvents );
+
+ // we don't own the object anymore
+ m_xOwnElement = NULL;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoContainerAction::implReRemove( ) SAL_THROW( ( Exception ) )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReRemove" );
+ Reference< XInterface > xElement;
+ if ( ( m_nIndex >= 0 ) && ( m_nIndex < m_xContainer->getCount() ) )
+ m_xContainer->getByIndex( m_nIndex ) >>= xElement;
+
+ if ( xElement != m_xElement )
+ {
+ // the indexes in the container changed. Okay, so go the long way and
+ // manually determine the index
+ m_nIndex = getElementPos( m_xContainer.get(), m_xElement );
+ if ( m_nIndex != -1 )
+ xElement = m_xElement;
+ }
+
+ OSL_ENSURE( xElement == m_xElement, "FmUndoContainerAction::implReRemove: cannot find the element which I'm responsible for!" );
+ if ( xElement == m_xElement )
+ {
+ Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
+ if ( xManager.is() )
+ m_aEvents = xManager->getScriptEvents( m_nIndex );
+ m_xContainer->removeByIndex( m_nIndex );
+ // from now on, we own this object
+ m_xOwnElement = m_xElement;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoContainerAction::Undo()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Undo" );
+ FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
+
+ if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
+ {
+ rEnv.Lock();
+ try
+ {
+ switch ( m_eAction )
+ {
+ case Inserted:
+ implReRemove();
+ break;
+
+ case Removed:
+ implReInsert();
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmUndoContainerAction::Undo: caught an exception!" );
+ }
+ rEnv.UnLock();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoContainerAction::Redo()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Redo" );
+ FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
+ if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
+ {
+ rEnv.Lock();
+ try
+ {
+ switch ( m_eAction )
+ {
+ case Inserted:
+ implReInsert();
+ break;
+
+ case Removed:
+ implReRemove();
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmUndoContainerAction::Redo: caught an exception!" );
+ }
+ rEnv.UnLock();
+ }
+}
+
+//------------------------------------------------------------------------------
+FmUndoModelReplaceAction::FmUndoModelReplaceAction(FmFormModel& _rMod, SdrUnoObj* _pObject, const Reference< XControlModel > & _xReplaced)
+ :SdrUndoAction(_rMod)
+ ,m_xReplaced(_xReplaced)
+ ,m_pObject(_pObject)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::FmUndoModelReplaceAction" );
+}
+
+//------------------------------------------------------------------------------
+FmUndoModelReplaceAction::~FmUndoModelReplaceAction()
+{
+ // dispose our element if nobody else is responsible for
+ DisposeElement(m_xReplaced);
+}
+
+//------------------------------------------------------------------------------
+
+void FmUndoModelReplaceAction::DisposeElement( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& xReplaced )
+{
+ Reference< XComponent > xComp(xReplaced, UNO_QUERY);
+ if (xComp.is())
+ {
+ Reference< XChild > xChild(xReplaced, UNO_QUERY);
+ if (!xChild.is() || !xChild->getParent().is())
+ xComp->dispose();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmUndoModelReplaceAction::Undo()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::Undo" );
+ try
+ {
+ Reference< XControlModel > xCurrentModel( m_pObject->GetUnoControlModel() );
+
+ // replace the model within the parent
+ Reference< XChild > xCurrentAsChild( xCurrentModel, UNO_QUERY );
+ Reference< XNameContainer > xCurrentsParent;
+ if ( xCurrentAsChild.is() )
+ xCurrentsParent = xCurrentsParent.query( xCurrentAsChild->getParent() );
+ DBG_ASSERT( xCurrentsParent.is(), "FmUndoModelReplaceAction::Undo: invalid current model!" );
+
+ if ( xCurrentsParent.is() )
+ {
+ // the form container works with FormComponents
+ Reference< XFormComponent > xComponent( m_xReplaced, UNO_QUERY );
+ DBG_ASSERT( xComponent.is(), "FmUndoModelReplaceAction::Undo: the new model is no form component !" );
+
+ Reference< XPropertySet > xCurrentAsSet( xCurrentModel, UNO_QUERY );
+ DBG_ASSERT( ::comphelper::hasProperty(FM_PROP_NAME, xCurrentAsSet ), "FmUndoModelReplaceAction::Undo : one of the models is invalid !");
+
+ ::rtl::OUString sName;
+ xCurrentAsSet->getPropertyValue( FM_PROP_NAME ) >>= sName;
+ xCurrentsParent->replaceByName( sName, makeAny( xComponent ) );
+
+ m_pObject->SetUnoControlModel(m_xReplaced);
+ m_pObject->SetChanged();
+
+ m_xReplaced = xCurrentModel;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmUndoModelReplaceAction::Undo : could not replace the model !");
+ }
+}
+
+//------------------------------------------------------------------------------
+String FmUndoModelReplaceAction::GetComment() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::GetComment" );
+ return SVX_RES(RID_STR_UNDO_MODEL_REPLACE);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmview.cxx b/svx/source/form/fmview.cxx
new file mode 100644
index 000000000000..b0a8ce637fc8
--- /dev/null
+++ b/svx/source/form/fmview.cxx
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <sfx2/docfile.hxx>
+#ifdef REFERENCE
+#undef REFERENCE
+#endif
+#include <svtools/ehdl.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/uno/XNamingService.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include "fmvwimp.hxx"
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <basic/sbuno.hxx>
+#include <sfx2/macrconf.hxx>
+#include <basic/sbx.hxx>
+#include "fmitems.hxx"
+#include "fmobj.hxx"
+#include "svditer.hxx"
+#include <svx/svdpagv.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/fmview.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/fmpage.hxx>
+#include <svx/fmshell.hxx>
+#include "fmpgeimp.hxx"
+#include "svx/fmtools.hxx"
+#include "fmshimp.hxx"
+#include "fmservs.hxx"
+#include "fmprop.hrc"
+#include "fmundo.hxx"
+#include <svx/dataaccessdescriptor.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <vcl/svapp.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/stdtext.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include "sdrpaintwindow.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::util;
+using namespace ::svxform;
+using namespace ::svx;
+
+//========================================================================
+//------------------------------------------------------------------------
+TYPEINIT1(FmFormView, E3dView);
+
+//------------------------------------------------------------------------
+FmFormView::FmFormView( FmFormModel* pModel, OutputDevice* pOut )
+ :E3dView(pModel,pOut)
+{
+ Init();
+}
+
+//------------------------------------------------------------------------
+void FmFormView::Init()
+{
+ pFormShell = NULL;
+ pImpl = new FmXFormView(::comphelper::getProcessServiceFactory(),this);
+ pImpl->acquire();
+
+ //////////////////////////////////////////////////////////////////////
+ // Model setzen
+ SdrModel* pModel = GetModel();
+
+ DBG_ASSERT( pModel->ISA(FmFormModel), "Falsches Model" );
+ if( !pModel->ISA(FmFormModel) ) return;
+ FmFormModel* pFormModel = (FmFormModel*)pModel;
+
+ //////////////////////////////////////////////////////////////////////
+ // DesignMode vom Model holen
+ sal_Bool bInitDesignMode = pFormModel->GetOpenInDesignMode();
+ if ( pFormModel->OpenInDesignModeIsDefaulted( ) )
+ { // this means that nobody ever explicitly set this on the model, and the model has never
+ // been loaded from a stream.
+ // This means this is a newly created document. This means, we want to have it in design
+ // mode by default (though a newly created model returns true for GetOpenInDesignMode).
+ // We _want_ to have this because it makes a lot of hacks following the original fix
+ // for #94595# unnecessary
+ // #96399# - 2002-10-11 - fs@openoffice.org
+ DBG_ASSERT( !bInitDesignMode, "FmFormView::Init: doesn't the model default to FALSE anymore?" );
+ // if this asserts, either the on-contruction default in the model has changed (then this here
+ // may not be necessary anymore), or we're not dealing with a new document ....
+ bInitDesignMode = sal_True;
+ }
+
+ SfxObjectShell* pObjShell = pFormModel->GetObjectShell();
+ if ( pObjShell && pObjShell->GetMedium() )
+ {
+ const SfxPoolItem *pItem=0;
+ if ( pObjShell->GetMedium()->GetItemSet()->GetItemState( SID_COMPONENTDATA, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ Sequence< PropertyValue > aSeq;
+ ( ((SfxUnoAnyItem*)pItem)->GetValue() ) >>= aSeq;
+ ::comphelper::NamedValueCollection aComponentData( aSeq );
+ bInitDesignMode = aComponentData.getOrDefault( "ApplyFormDesignMode", bInitDesignMode );
+ }
+ }
+
+ if( pObjShell && pObjShell->IsReadOnly() )
+ bInitDesignMode = sal_False;
+
+ // dieses wird in der Shell vorgenommen
+ // bDesignMode = !bInitDesignMode; // erzwingt, dass SetDesignMode ausgefuehrt wird
+ SetDesignMode( bInitDesignMode );
+}
+
+//------------------------------------------------------------------------
+FmFormView::~FmFormView()
+{
+ if( pFormShell )
+ pFormShell->SetView( NULL );
+
+ pImpl->notifyViewDying();
+ pImpl->release();
+ pImpl = NULL;
+}
+
+//------------------------------------------------------------------------
+FmFormPage* FmFormView::GetCurPage()
+{
+ SdrPageView* pPageView = GetSdrPageView();
+ FmFormPage* pCurPage = pPageView ? PTR_CAST( FmFormPage, pPageView->GetPage() ) : NULL;
+ return pCurPage;
+}
+
+//------------------------------------------------------------------------
+void FmFormView::MarkListHasChanged()
+{
+ E3dView::MarkListHasChanged();
+
+ if ( pFormShell && IsDesignMode() )
+ {
+ FmFormObj* pObj = getMarkedGrid();
+ if ( pImpl->m_pMarkedGrid && pImpl->m_pMarkedGrid != pObj )
+ {
+ pImpl->m_pMarkedGrid = NULL;
+ if ( pImpl->m_xWindow.is() )
+ {
+ pImpl->m_xWindow->removeFocusListener(pImpl);
+ pImpl->m_xWindow = NULL;
+ }
+ SetMoveOutside(FALSE);
+ //OLMRefreshAllIAOManagers();
+ }
+
+ pFormShell->GetImpl()->SetSelectionDelayed();
+ }
+}
+
+namespace
+{
+ const SdrPageWindow* findPageWindow( const SdrPaintView* _pView, OutputDevice* _pWindow )
+ {
+ SdrPageView* pPageView = _pView->GetSdrPageView();
+ if(pPageView)
+ {
+ for ( sal_uInt32 window = 0; window < pPageView->PageWindowCount(); ++window )
+ {
+ const SdrPageWindow* pPageWindow = pPageView->GetPageWindow( window );
+ if ( !pPageWindow || &pPageWindow->GetPaintWindow().GetOutputDevice() != _pWindow )
+ continue;
+
+ return pPageWindow;
+ }
+ }
+ return NULL;
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormView::AddWindowToPaintView(OutputDevice* pNewWin)
+{
+ E3dView::AddWindowToPaintView(pNewWin);
+
+ if ( !pNewWin )
+ return;
+
+ // look up the PageViewWindow for the newly inserted window, and care for it
+ // #i39269# / 2004-12-20 / frank.schoenheit@sun.com
+ const SdrPageWindow* pPageWindow = findPageWindow( this, pNewWin );
+ if ( pPageWindow )
+ pImpl->addWindow( *pPageWindow );
+}
+
+//------------------------------------------------------------------------
+void FmFormView::DeleteWindowFromPaintView(OutputDevice* pNewWin)
+{
+ const SdrPageWindow* pPageWindow = findPageWindow( this, pNewWin );
+ if ( pPageWindow )
+ pImpl->removeWindow( pPageWindow->GetControlContainer() );
+
+ E3dView::DeleteWindowFromPaintView(pNewWin);
+}
+
+//------------------------------------------------------------------------
+void FmFormView::ChangeDesignMode(sal_Bool bDesign)
+{
+ if (bDesign == IsDesignMode())
+ return;
+
+ FmFormModel* pModel = PTR_CAST(FmFormModel, GetModel());
+ if (pModel)
+ { // fuer die Zeit des Uebergangs das Undo-Environment ausschalten, das sichert, dass man dort auch nicht-transiente
+ // Properties mal eben aendern kann (sollte allerdings mit Vorsicht genossen und beim Rueckschalten des Modes
+ // auch immer wieder rueckgaegig gemacht werden. Ein Beispiel ist das Setzen der maximalen Text-Laenge durch das
+ // FmXEditModel an seinem Control.)
+ pModel->GetUndoEnv().Lock();
+ }
+
+ // --- 1. deactivate all controls if we are switching to design mode
+ if ( bDesign )
+ DeactivateControls( GetSdrPageView() );
+
+ // --- 2. simulate a deactivation (the shell will handle some things there ...?)
+ if ( pFormShell && pFormShell->GetImpl() )
+ pFormShell->GetImpl()->viewDeactivated( *this, sal_True );
+ else
+ pImpl->Deactivate( sal_True );
+
+ // --- 3. activate all controls, if we're switching to alive mode
+ if ( !bDesign )
+ ActivateControls( GetSdrPageView() );
+
+ // --- 4. load resp. unload the forms
+ FmFormPage* pCurPage = GetCurPage();
+ if ( pCurPage )
+ {
+ if ( pFormShell && pFormShell->GetImpl() )
+ pFormShell->GetImpl()->loadForms( pCurPage, ( bDesign ? FORMS_UNLOAD : FORMS_LOAD ) );
+ }
+
+ // --- 5. base class functionality
+ SetDesignMode( bDesign );
+
+ // --- 6. simulate a activation (the shell will handle some things there ...?)
+ OSL_PRECOND( pFormShell && pFormShell->GetImpl(), "FmFormView::ChangeDesignMode: is this really allowed? No shell?" );
+ if ( pFormShell && pFormShell->GetImpl() )
+ pFormShell->GetImpl()->viewActivated( *this );
+ else
+ pImpl->Activate();
+
+ if ( pCurPage )
+ {
+ if ( bDesign )
+ {
+ if ( GetActualOutDev() && GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ const Window* pWindow = static_cast< const Window* >( GetActualOutDev() );
+ const_cast< Window* >( pWindow )->GrabFocus();
+ }
+
+ // redraw UNO objects
+ if ( GetSdrPageView() )
+ {
+ SdrObjListIter aIter(*pCurPage);
+ while( aIter.IsMore() )
+ {
+ SdrObject* pObj = aIter.Next();
+ if (pObj && pObj->IsUnoObj())
+ {
+ // For redraw just use ActionChanged()
+ // pObj->BroadcastObjectChange();
+ pObj->ActionChanged();
+ }
+ }
+ }
+ }
+ else
+ {
+ // set the auto focus to the first control (if indicated by the model to do so)
+ sal_Bool bForceControlFocus = pModel ? pModel->GetAutoControlFocus() : sal_False;
+ if (bForceControlFocus)
+ pImpl->AutoFocus();
+ }
+ }
+
+ // und mein Undo-Environment wieder an
+ if (pModel)
+ pModel->GetUndoEnv().UnLock();
+}
+
+//------------------------------------------------------------------------
+void FmFormView::GrabFirstControlFocus( sal_Bool _bForceSync )
+{
+ if ( !IsDesignMode() )
+ pImpl->AutoFocus( _bForceSync );
+}
+
+//------------------------------------------------------------------------
+SdrPageView* FmFormView::ShowSdrPage(SdrPage* pPage)
+{
+ SdrPageView* pPV = E3dView::ShowSdrPage(pPage);
+
+ if (pPage)
+ {
+ if (!IsDesignMode())
+ {
+ // creating the controllers
+ ActivateControls(pPV);
+
+ // Alles deselektieren
+ UnmarkAll();
+ }
+ else if ( pFormShell && pFormShell->IsDesignMode() )
+ {
+ FmXFormShell* pFormShellImpl = pFormShell->GetImpl();
+ pFormShellImpl->UpdateForms( sal_True );
+
+ // damit der Formular-Navigator auf den Seitenwechsel reagieren kann
+ pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_FMEXPLORER_CONTROL , sal_True, sal_False);
+
+ pFormShellImpl->SetSelection(GetMarkedObjectList());
+ }
+ }
+
+ // notify our shell that we have been activated
+ if ( pFormShell && pFormShell->GetImpl() )
+ pFormShell->GetImpl()->viewActivated( *this );
+ else
+ pImpl->Activate();
+
+ return pPV;
+}
+
+//------------------------------------------------------------------------
+void FmFormView::HideSdrPage()
+{
+ // --- 1. deactivate controls
+ if ( !IsDesignMode() )
+ DeactivateControls(GetSdrPageView());
+
+ // --- 2. tell the shell the view is (going to be) deactivated
+ if ( pFormShell && pFormShell->GetImpl() )
+ pFormShell->GetImpl()->viewDeactivated( *this, sal_True );
+ else
+ pImpl->Deactivate( sal_True );
+
+ // --- 3. base class behavior
+ E3dView::HideSdrPage();
+}
+
+//------------------------------------------------------------------------
+SdrModel* FmFormView::GetMarkedObjModel() const
+{
+ return E3dView::GetMarkedObjModel();
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmFormView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
+{
+ return E3dView::Paste(rMod, rPos, pLst, nOptions);
+}
+
+//------------------------------------------------------------------------
+void FmFormView::ActivateControls(SdrPageView* pPageView)
+{
+ if (!pPageView)
+ return;
+
+ for (sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); ++i)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
+ pImpl->addWindow(rPageWindow);
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormView::DeactivateControls(SdrPageView* pPageView)
+{
+ if( !pPageView )
+ return;
+
+ for (sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); ++i)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
+ pImpl->removeWindow(rPageWindow.GetControlContainer() );
+ }
+}
+
+//------------------------------------------------------------------------
+SdrObject* FmFormView::CreateFieldControl( const ODataAccessDescriptor& _rColumnDescriptor )
+{
+ return pImpl->implCreateFieldControl( _rColumnDescriptor );
+}
+
+//------------------------------------------------------------------------
+SdrObject* FmFormView::CreateXFormsControl( const OXFormsDescriptor &_rDesc )
+{
+ return pImpl->implCreateXFormsControl(_rDesc);
+}
+
+//------------------------------------------------------------------------
+SdrObject* FmFormView::CreateFieldControl(const UniString& rFieldDesc) const
+{
+ ::rtl::OUString sDataSource = rFieldDesc.GetToken(0,sal_Unicode(11));
+ ::rtl::OUString sObjectName = rFieldDesc.GetToken(1,sal_Unicode(11));
+ sal_uInt16 nObjectType = (sal_uInt16)rFieldDesc.GetToken(2,sal_Unicode(11)).ToInt32();
+ ::rtl::OUString sFieldName = rFieldDesc.GetToken(3,sal_Unicode(11));
+
+ if (!sFieldName.getLength() || !sObjectName.getLength() || !sDataSource.getLength())
+ return NULL;
+
+ ODataAccessDescriptor aColumnDescriptor;
+ aColumnDescriptor.setDataSource(sDataSource);
+ aColumnDescriptor[ daCommand ] <<= sObjectName;
+ aColumnDescriptor[ daCommandType ] <<= nObjectType;
+ aColumnDescriptor[ daColumnName ] <<= sFieldName;
+
+ return pImpl->implCreateFieldControl( aColumnDescriptor );
+}
+
+//------------------------------------------------------------------------
+void FmFormView::InsertControlContainer(const Reference< ::com::sun::star::awt::XControlContainer > & xCC)
+{
+ if( !IsDesignMode() )
+ {
+ SdrPageView* pPageView = GetSdrPageView();
+ if( pPageView )
+ {
+ for( sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); i++ )
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
+
+ if( rPageWindow.GetControlContainer( false ) == xCC )
+ {
+ pImpl->addWindow(rPageWindow);
+ break;
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+void FmFormView::RemoveControlContainer(const Reference< ::com::sun::star::awt::XControlContainer > & xCC)
+{
+ if( !IsDesignMode() )
+ {
+ pImpl->removeWindow( xCC );
+ }
+}
+
+// -----------------------------------------------------------------------------
+SdrPaintWindow* FmFormView::BeginCompleteRedraw(OutputDevice* pOut)
+{
+ SdrPaintWindow* pPaintWindow = E3dView::BeginCompleteRedraw( pOut );
+ pImpl->suspendTabOrderUpdate();
+ return pPaintWindow;
+}
+
+// -----------------------------------------------------------------------------
+void FmFormView::EndCompleteRedraw( SdrPaintWindow& rPaintWindow, bool bPaintFormLayer )
+{
+ E3dView::EndCompleteRedraw( rPaintWindow, bPaintFormLayer );
+ pImpl->resumeTabOrderUpdate();
+}
+
+// -----------------------------------------------------------------------------
+BOOL FmFormView::KeyInput(const KeyEvent& rKEvt, Window* pWin)
+{
+ BOOL bDone = FALSE;
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ if ( IsDesignMode()
+ && rKeyCode.GetCode() == KEY_RETURN
+ )
+ {
+ // RETURN alone enters grid controls, for keyboard accessibility
+ if ( pWin
+ && !rKeyCode.IsShift()
+ && !rKeyCode.IsMod1()
+ && !rKeyCode.IsMod2()
+ )
+ {
+ FmFormObj* pObj = getMarkedGrid();
+ if ( pObj )
+ {
+ Reference< awt::XWindow > xWindow( pObj->GetUnoControl( *this, *pWin ), UNO_QUERY );
+ if ( xWindow.is() )
+ {
+ pImpl->m_pMarkedGrid = pObj;
+ pImpl->m_xWindow = xWindow;
+ // add as listener to get notified when ESC will be pressed inside the grid
+ pImpl->m_xWindow->addFocusListener(pImpl);
+ SetMoveOutside(TRUE);
+ //OLMRefreshAllIAOManagers();
+ xWindow->setFocus();
+ bDone = TRUE;
+ }
+ }
+ }
+ // Alt-RETURN alone shows the properties of the selection
+ if ( pFormShell
+ && pFormShell->GetImpl()
+ && !rKeyCode.IsShift()
+ && !rKeyCode.IsMod1()
+ && rKeyCode.IsMod2()
+ )
+ {
+ pFormShell->GetImpl()->handleShowPropertiesRequest();
+ }
+
+ }
+
+ if ( !bDone )
+ bDone = E3dView::KeyInput(rKEvt,pWin);
+ return bDone;
+}
+// -----------------------------------------------------------------------------
+sal_Bool FmFormView::checkUnMarkAll(const Reference< XInterface >& _xSource)
+{
+ Reference< ::com::sun::star::awt::XControl> xControl(pImpl->m_xWindow,UNO_QUERY);
+ sal_Bool bRet = !xControl.is() || !_xSource.is() || _xSource != xControl->getModel();
+ if ( bRet )
+ UnmarkAll();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+BOOL FmFormView::MouseButtonDown( const MouseEvent& _rMEvt, Window* _pWin )
+{
+ BOOL bReturn = E3dView::MouseButtonDown( _rMEvt, _pWin );
+
+ if ( pFormShell && pFormShell->GetImpl() )
+ {
+ SdrViewEvent aViewEvent;
+ PickAnything( _rMEvt, SDRMOUSEBUTTONDOWN, aViewEvent );
+ pFormShell->GetImpl()->handleMouseButtonDown( aViewEvent );
+ }
+
+ return bReturn;
+}
+
+// -----------------------------------------------------------------------------
+FmFormObj* FmFormView::getMarkedGrid() const
+{
+ FmFormObj* pFormObject = NULL;
+ const SdrMarkList& rMarkList = GetMarkedObjectList();
+ if ( 1 == rMarkList.GetMarkCount() )
+ {
+ SdrMark* pMark = rMarkList.GetMark(0);
+ if ( pMark )
+ {
+ pFormObject = FmFormObj::GetFormObject( pMark->GetMarkedSdrObj() );
+ if ( pFormObject )
+ {
+ Reference< XServiceInfo > xServInfo( pFormObject->GetUnoControlModel(), UNO_QUERY );
+ if ( !xServInfo.is() || !xServInfo->supportsService( FM_SUN_COMPONENT_GRIDCONTROL ) )
+ pFormObject = NULL;
+ }
+ }
+ }
+ return pFormObject;
+}
+
+// -----------------------------------------------------------------------------
+void FmFormView::createControlLabelPair( OutputDevice* _pOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
+ const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats,
+ sal_uInt16 _nControlObjectID, const ::rtl::OUString& _rFieldPostfix, UINT32 _nInventor, UINT16 _nLabelObjectID,
+ SdrPage* _pLabelPage, SdrPage* _pControlPage, SdrModel* _pModel, SdrUnoObj*& _rpLabel, SdrUnoObj*& _rpControl )
+{
+ FmXFormView::createControlLabelPair(
+ ::comphelper::getProcessServiceFactory(),
+ *_pOutDev, _nXOffsetMM, _nYOffsetMM,
+ _rxField, _rxNumberFormats,
+ _nControlObjectID, _rFieldPostfix, _nInventor, _nLabelObjectID,
+ _pLabelPage, _pControlPage, _pModel,
+ _rpLabel, _rpControl
+ );
+}
+// -----------------------------------------------------------------------------
+Reference< runtime::XFormController > FmFormView::GetFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const
+{
+ return pImpl->getFormController( _rxForm, _rDevice );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/fmvwimp.cxx b/svx/source/form/fmvwimp.cxx
new file mode 100644
index 000000000000..2af37dccd535
--- /dev/null
+++ b/svx/source/form/fmvwimp.cxx
@@ -0,0 +1,1961 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmdocumentclassification.hxx"
+#include "fmobj.hxx"
+#include "fmpgeimp.hxx"
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "fmshimp.hxx"
+#include "svx/fmtools.hxx"
+#include "fmundo.hxx"
+#include "fmvwimp.hxx"
+#include "formcontrolfactory.hxx"
+#include "sdrpaintwindow.hxx"
+#include "svditer.hxx"
+#include "svx/dataaccessdescriptor.hxx"
+#include "svx/dialmgr.hxx"
+#include "svx/fmglob.hxx"
+#include "svx/fmmodel.hxx"
+#include "svx/fmpage.hxx"
+#include "svx/fmshell.hxx"
+#include "svx/fmview.hxx"
+#include "svx/sdrpagewindow.hxx"
+#include "svx/svdogrp.hxx"
+#include "svx/svdpagv.hxx"
+#include "xmlexchg.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormats.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/form/binding/XBindableValue.hpp>
+#include <com/sun/star/form/binding/XValueBinding.hpp>
+#include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/awt/XTabController.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/numbers.hxx>
+#include <comphelper/property.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/msgbox.hxx>
+#include <vcl/stdtext.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/logfile.hxx>
+
+#include <algorithm>
+
+using namespace ::comphelper;
+using namespace ::svx;
+using namespace ::svxform;
+
+ using namespace ::com::sun::star;
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::style::VerticalAlignment_MIDDLE;
+ using ::com::sun::star::form::FormButtonType_SUBMIT;
+ using ::com::sun::star::form::binding::XValueBinding;
+ using ::com::sun::star::form::binding::XBindableValue;
+ using ::com::sun::star::lang::XComponent;
+ using ::com::sun::star::container::XIndexAccess;
+ using ::com::sun::star::form::XForm;
+ using ::com::sun::star::form::runtime::XFormController;
+ using ::com::sun::star::script::XEventAttacherManager;
+ using ::com::sun::star::awt::XTabControllerModel;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::container::XEnumeration;
+ using ::com::sun::star::task::XInteractionHandler;
+ using ::com::sun::star::lang::XInitialization;
+ using ::com::sun::star::awt::XTabController;
+ using ::com::sun::star::lang::XUnoTunnel;
+ using ::com::sun::star::awt::XControlContainer;
+ using ::com::sun::star::awt::XControl;
+ using ::com::sun::star::form::XFormComponent;
+ using ::com::sun::star::form::XForm;
+ using ::com::sun::star::lang::IndexOutOfBoundsException;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::container::XContainer;
+ using ::com::sun::star::container::ContainerEvent;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::beans::NamedValue;
+ using ::com::sun::star::sdb::SQLErrorEvent;
+ using ::com::sun::star::sdbc::XRowSet;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::container::XElementAccess;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::awt::FocusEvent;
+ using ::com::sun::star::ui::dialogs::XExecutableDialog;
+ using ::com::sun::star::sdbc::XDataSource;
+ using ::com::sun::star::container::XIndexContainer;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::sdb::SQLContext;
+ using ::com::sun::star::sdbc::SQLWarning;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::util::XNumberFormats;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ /** === end UNO using === **/
+ namespace FormComponentType = ::com::sun::star::form::FormComponentType;
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+ namespace DataType = ::com::sun::star::sdbc::DataType;
+
+//------------------------------------------------------------------------------
+class FmXFormView::ObjectRemoveListener : public SfxListener
+{
+ FmXFormView* m_pParent;
+public:
+ ObjectRemoveListener( FmXFormView* pParent );
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+};
+
+//========================================================================
+DBG_NAME(FmXPageViewWinRec)
+//------------------------------------------------------------------------
+FmXPageViewWinRec::FmXPageViewWinRec( const ::comphelper::ComponentContext& _rContext, const SdrPageWindow& _rWindow, FmXFormView* _pViewImpl )
+: m_xControlContainer( _rWindow.GetControlContainer() ),
+ m_aContext( _rContext ),
+ m_pViewImpl( _pViewImpl ),
+ m_pWindow( dynamic_cast< Window* >( &_rWindow.GetPaintWindow().GetOutputDevice() ) )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::FmXPageViewWinRec" );
+ DBG_CTOR(FmXPageViewWinRec,NULL);
+
+ // create an XFormController for every form
+ FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( _rWindow.GetPageView().GetPage() );
+ DBG_ASSERT( pFormPage, "FmXPageViewWinRec::FmXPageViewWinRec: no FmFormPage found!" );
+ if ( pFormPage )
+ {
+ try
+ {
+ Reference< XIndexAccess > xForms( pFormPage->GetForms(), UNO_QUERY_THROW );
+ sal_uInt32 nLength = xForms->getCount();
+ for (sal_uInt32 i = 0; i < nLength; i++)
+ {
+ Reference< XForm > xForm( xForms->getByIndex(i), UNO_QUERY );
+ if ( xForm.is() )
+ setController( xForm, NULL );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+FmXPageViewWinRec::~FmXPageViewWinRec()
+{
+ DBG_DTOR(FmXPageViewWinRec,NULL);
+}
+
+//------------------------------------------------------------------
+void FmXPageViewWinRec::dispose()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::dispose" );
+ for ( ::std::vector< Reference< XFormController > >::const_iterator i = m_aControllerList.begin();
+ i != m_aControllerList.end();
+ ++i
+ )
+ {
+ try
+ {
+ Reference< XFormController > xController( *i, UNO_QUERY_THROW );
+
+ // detaching the events
+ Reference< XChild > xControllerModel( xController->getModel(), UNO_QUERY );
+ if ( xControllerModel.is() )
+ {
+ Reference< XEventAttacherManager > xEventManager( xControllerModel->getParent(), UNO_QUERY_THROW );
+ Reference< XInterface > xControllerNormalized( xController, UNO_QUERY_THROW );
+ xEventManager->detach( i - m_aControllerList.begin(), xControllerNormalized );
+ }
+
+ // dispose the formcontroller
+ Reference< XComponent > xComp( xController, UNO_QUERY_THROW );
+ xComp->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ m_aControllerList.clear();
+}
+
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FmXPageViewWinRec::hasElements(void) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::hasElements" );
+ return getCount() != 0;
+}
+
+//------------------------------------------------------------------------------
+Type SAL_CALL FmXPageViewWinRec::getElementType(void) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::getElementType" );
+ return ::getCppuType((const Reference< XFormController>*)0);
+}
+
+// XEnumerationAccess
+//------------------------------------------------------------------------------
+Reference< XEnumeration > SAL_CALL FmXPageViewWinRec::createEnumeration(void) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::createEnumeration" );
+ return new ::comphelper::OEnumerationByIndex(this);
+}
+
+// XIndexAccess
+//------------------------------------------------------------------------------
+sal_Int32 SAL_CALL FmXPageViewWinRec::getCount(void) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::getCount" );
+ return m_aControllerList.size();
+}
+
+//------------------------------------------------------------------------------
+Any SAL_CALL FmXPageViewWinRec::getByIndex(sal_Int32 nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::getByIndex" );
+ if (nIndex < 0 ||
+ nIndex >= getCount())
+ throw IndexOutOfBoundsException();
+
+ Any aElement;
+ aElement <<= m_aControllerList[nIndex];
+ return aElement;
+}
+
+//------------------------------------------------------------------------
+void SAL_CALL FmXPageViewWinRec::makeVisible( const Reference< XControl >& _Control ) throw (RuntimeException)
+{
+ SolarMutexGuard aSolarGuard;
+
+ Reference< XWindow > xWindow( _Control, UNO_QUERY );
+ if ( xWindow.is() && m_pViewImpl->getView() && m_pWindow )
+ {
+ awt::Rectangle aRect = xWindow->getPosSize();
+ ::Rectangle aNewRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height );
+ aNewRect = m_pWindow->PixelToLogic( aNewRect );
+ m_pViewImpl->getView()->MakeVisible( aNewRect, *m_pWindow );
+ }
+}
+
+//------------------------------------------------------------------------
+Reference< XFormController > getControllerSearchChilds( const Reference< XIndexAccess > & xIndex, const Reference< XTabControllerModel > & xModel)
+{
+ if (xIndex.is() && xIndex->getCount())
+ {
+ Reference< XFormController > xController;
+
+ for (sal_Int32 n = xIndex->getCount(); n-- && !xController.is(); )
+ {
+ xIndex->getByIndex(n) >>= xController;
+ if ((XTabControllerModel*)xModel.get() == (XTabControllerModel*)xController->getModel().get())
+ return xController;
+ else
+ {
+ xController = getControllerSearchChilds(Reference< XIndexAccess > (xController, UNO_QUERY), xModel);
+ if ( xController.is() )
+ return xController;
+ }
+ }
+ }
+ return Reference< XFormController > ();
+}
+
+// Search the according controller
+//------------------------------------------------------------------------
+Reference< XFormController > FmXPageViewWinRec::getController( const Reference< XForm > & xForm ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::getController" );
+ Reference< XTabControllerModel > xModel(xForm, UNO_QUERY);
+ for (::std::vector< Reference< XFormController > >::const_iterator i = m_aControllerList.begin();
+ i != m_aControllerList.end(); i++)
+ {
+ if ((XTabControllerModel*)(*i)->getModel().get() == (XTabControllerModel*)xModel.get())
+ return *i;
+
+ // the current-round controller isn't the right one. perhaps one of it's children ?
+ Reference< XFormController > xChildSearch = getControllerSearchChilds(Reference< XIndexAccess > (*i, UNO_QUERY), xModel);
+ if (xChildSearch.is())
+ return xChildSearch;
+ }
+ return Reference< XFormController > ();
+}
+
+//------------------------------------------------------------------------
+void FmXPageViewWinRec::setController(const Reference< XForm > & xForm, const Reference< XFormController >& _rxParentController )
+{
+ DBG_ASSERT( xForm.is(), "FmXPageViewWinRec::setController: there should be a form!" );
+ Reference< XIndexAccess > xFormCps(xForm, UNO_QUERY);
+ if (!xFormCps.is())
+ return;
+
+ Reference< XTabControllerModel > xTabOrder(xForm, UNO_QUERY);
+
+ // create a form controller
+ Reference< XFormController > xController( m_aContext.createComponent( FM_FORM_CONTROLLER ), UNO_QUERY );
+ if ( !xController.is() )
+ {
+ ShowServiceNotAvailableError( m_pWindow, FM_FORM_CONTROLLER, sal_True );
+ return;
+ }
+
+ Reference< XInteractionHandler > xHandler;
+ if ( _rxParentController.is() )
+ xHandler = _rxParentController->getInteractionHandler();
+ else
+ {
+ // TODO: should we create a default handler? Not really necessary, since the
+ // FormController itself has a default fallback
+ }
+ if ( xHandler.is() )
+ xController->setInteractionHandler( xHandler );
+
+ xController->setContext( this );
+
+ xController->setModel( xTabOrder );
+ xController->setContainer( m_xControlContainer );
+ xController->activateTabOrder();
+ xController->addActivateListener( m_pViewImpl );
+
+ if ( _rxParentController.is() )
+ _rxParentController->addChildController( xController );
+ else
+ {
+ m_aControllerList.push_back(xController);
+
+ xController->setParent( *this );
+
+ // attaching the events
+ Reference< XEventAttacherManager > xEventManager( xForm->getParent(), UNO_QUERY );
+ Reference< XInterface > xIfc(xController, UNO_QUERY);
+ xEventManager->attach(m_aControllerList.size() - 1, xIfc, makeAny(xController) );
+ }
+
+ // jetzt die Subforms durchgehen
+ sal_uInt32 nLength = xFormCps->getCount();
+ Reference< XForm > xSubForm;
+ for (sal_uInt32 i = 0; i < nLength; i++)
+ {
+ if ( xFormCps->getByIndex(i) >>= xSubForm )
+ setController( xSubForm, xController );
+ }
+}
+
+//------------------------------------------------------------------------
+void FmXPageViewWinRec::updateTabOrder( const Reference< XForm >& _rxForm )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXPageViewWinRec::updateTabOrder" );
+ OSL_PRECOND( _rxForm.is(), "FmXPageViewWinRec::updateTabOrder: illegal argument!" );
+ if ( !_rxForm.is() )
+ return;
+
+ try
+ {
+ Reference< XTabController > xTabCtrl( getController( _rxForm ).get() );
+ if ( xTabCtrl.is() )
+ { // if there already is a TabController for this form, then delegate the "updateTabOrder" request
+ xTabCtrl->activateTabOrder();
+ }
+ else
+ { // otherwise, create a TabController
+
+ // if it's a sub form, then we must ensure there exist TabControllers
+ // for all its ancestors, too
+ Reference< XForm > xParentForm( _rxForm->getParent(), UNO_QUERY );
+ // there is a parent form -> look for the respective controller
+ Reference< XFormController > xParentController;
+ if ( xParentForm.is() )
+ xParentController.set( getController( xParentForm ), UNO_QUERY );
+
+ setController( _rxForm, xParentController );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------
+FmXFormView::FmXFormView(const ::comphelper::ComponentContext& _rContext, FmFormView* _pView )
+ :m_aContext( _rContext )
+ ,m_pMarkedGrid(NULL)
+ ,m_pView(_pView)
+ ,m_nActivationEvent(0)
+ ,m_nErrorMessageEvent( 0 )
+ ,m_nAutoFocusEvent( 0 )
+ ,m_nControlWizardEvent( 0 )
+ ,m_pWatchStoredList( NULL )
+ ,m_bFirstActivation( true )
+ ,m_isTabOrderUpdateSuspended( false )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::FmXFormView" );
+}
+
+//------------------------------------------------------------------------
+void FmXFormView::cancelEvents()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::cancelEvents" );
+ if ( m_nActivationEvent )
+ {
+ Application::RemoveUserEvent( m_nActivationEvent );
+ m_nActivationEvent = 0;
+ }
+
+ if ( m_nErrorMessageEvent )
+ {
+ Application::RemoveUserEvent( m_nErrorMessageEvent );
+ m_nErrorMessageEvent = 0;
+ }
+
+ if ( m_nAutoFocusEvent )
+ {
+ Application::RemoveUserEvent( m_nAutoFocusEvent );
+ m_nAutoFocusEvent = 0;
+ }
+
+ if ( m_nControlWizardEvent )
+ {
+ Application::RemoveUserEvent( m_nControlWizardEvent );
+ m_nControlWizardEvent = 0;
+ }
+}
+
+//------------------------------------------------------------------------
+void FmXFormView::notifyViewDying( )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::notifyViewDying" );
+ DBG_ASSERT( m_pView, "FmXFormView::notifyViewDying: my view already died!" );
+ m_pView = NULL;
+ cancelEvents();
+}
+
+//------------------------------------------------------------------------
+FmXFormView::~FmXFormView()
+{
+ DBG_ASSERT(m_aWinList.size() == 0, "FmXFormView::~FmXFormView: Window list not empty!");
+
+ cancelEvents();
+
+ delete m_pWatchStoredList;
+ m_pWatchStoredList = NULL;
+}
+
+// EventListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::disposing(const EventObject& Source) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::disposing" );
+ if ( m_xWindow.is() && Source.Source == m_xWindow )
+ removeGridWindowListening();
+}
+
+// XFormControllerListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::formActivated(const EventObject& rEvent) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::formActivated" );
+ if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() )
+ m_pView->GetFormShell()->GetImpl()->formActivated( rEvent );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::formDeactivated(const EventObject& rEvent) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::formDeactivated" );
+ if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() )
+ m_pView->GetFormShell()->GetImpl()->formDeactivated( rEvent );
+}
+
+// XContainerListener
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::elementInserted(const ContainerEvent& evt) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::elementInserted" );
+ try
+ {
+ Reference< XControlContainer > xControlContainer( evt.Source, UNO_QUERY_THROW );
+ Reference< XControl > xControl( evt.Element, UNO_QUERY_THROW );
+ Reference< XFormComponent > xControlModel( xControl->getModel(), UNO_QUERY_THROW );
+ Reference< XForm > xForm( xControlModel->getParent(), UNO_QUERY_THROW );
+
+ if ( m_isTabOrderUpdateSuspended )
+ {
+ // remember the container and the control, so we can update the tab order on resumeTabOrderUpdate
+ m_aNeedTabOrderUpdate[ xControlContainer ].insert( xForm );
+ }
+ else
+ {
+ FmWinRecList::iterator pos = findWindow( xControlContainer );
+ if ( pos != m_aWinList.end() )
+ {
+ (*pos)->updateTabOrder( xForm );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::elementReplaced(const ContainerEvent& evt) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::elementReplaced" );
+ elementInserted(evt);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FmXFormView::elementRemoved(const ContainerEvent& /*evt*/) throw( RuntimeException )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::elementRemoved" );
+}
+
+//------------------------------------------------------------------------------
+FmWinRecList::const_iterator FmXFormView::findWindow( const Reference< XControlContainer >& _rxCC ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::findWindow" );
+ for (FmWinRecList::const_iterator i = m_aWinList.begin();
+ i != m_aWinList.end(); ++i)
+ {
+ if ( _rxCC == (*i)->getControlContainer() )
+ return i;
+ }
+ return m_aWinList.end();
+}
+
+//------------------------------------------------------------------------------
+FmWinRecList::iterator FmXFormView::findWindow( const Reference< XControlContainer >& _rxCC )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::findWindow" );
+ for (FmWinRecList::iterator i = m_aWinList.begin();
+ i != m_aWinList.end(); ++i)
+ {
+ if ( _rxCC == (*i)->getControlContainer() )
+ return i;
+ }
+ return m_aWinList.end();
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::addWindow(const SdrPageWindow& rWindow)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::addWindow" );
+ FmFormPage* pFormPage = PTR_CAST( FmFormPage, rWindow.GetPageView().GetPage() );
+ if ( !pFormPage )
+ return;
+
+ Reference< XControlContainer > xCC = rWindow.GetControlContainer();
+ if ( xCC.is() && findWindow( xCC ) == m_aWinList.end())
+ {
+ FmXPageViewWinRec *pFmRec = new FmXPageViewWinRec( m_aContext, rWindow, this );
+ pFmRec->acquire();
+
+ m_aWinList.push_back(pFmRec);
+
+ // Am ControlContainer horchen um Aenderungen mitzbekommen
+ Reference< XContainer > xContainer( xCC, UNO_QUERY );
+ if (xContainer.is())
+ xContainer->addContainerListener(this);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::removeWindow( const Reference< XControlContainer >& _rxCC )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::removeWindow" );
+ // Wird gerufen, wenn
+ // - in den Design-Modus geschaltet wird
+ // - ein Window geloescht wird, waehrend man im Design-Modus ist
+ // - der Control-Container fuer ein Window entfernt wird, waehrend
+ // der aktive Modus eingeschaltet ist.
+ FmWinRecList::iterator i = findWindow( _rxCC );
+ if (i != m_aWinList.end())
+ {
+ // Am ControlContainer horchen um Aenderungen mitzbekommen
+ Reference< XContainer > xContainer( _rxCC, UNO_QUERY );
+ if (xContainer.is())
+ xContainer->removeContainerListener(this);
+
+ (*i)->dispose();
+ (*i)->release();
+ m_aWinList.erase(i);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::displayAsyncErrorMessage( const SQLErrorEvent& _rEvent )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::displayAsyncErrorMessage" );
+ DBG_ASSERT( 0 == m_nErrorMessageEvent, "FmXFormView::displayAsyncErrorMessage: not too fast, please!" );
+ // This should not happen - usually, the PostUserEvent is faster than any possible user
+ // interaction which could trigger a new error. If it happens, we need a queue for the events.
+ m_aAsyncError = _rEvent;
+ m_nErrorMessageEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnDelayedErrorMessage ) );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormView, OnDelayedErrorMessage, void*, /*EMPTYTAG*/)
+{
+ m_nErrorMessageEvent = 0;
+ displayException( m_aAsyncError );
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::onFirstViewActivation( const FmFormModel* _pDocModel )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::onFirstViewActivation" );
+ if ( _pDocModel && _pDocModel->GetAutoControlFocus() )
+ m_nAutoFocusEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnAutoFocus ) );
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::suspendTabOrderUpdate()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::suspendTabOrderUpdate" );
+ OSL_ENSURE( !m_isTabOrderUpdateSuspended, "FmXFormView::suspendTabOrderUpdate: nesting not allowed!" );
+ m_isTabOrderUpdateSuspended = true;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::resumeTabOrderUpdate()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::resumeTabOrderUpdate" );
+ OSL_ENSURE( m_isTabOrderUpdateSuspended, "FmXFormView::resumeTabOrderUpdate: not suspended!" );
+ m_isTabOrderUpdateSuspended = false;
+
+ // update the tab orders for all components which were collected since the suspendTabOrderUpdate call.
+ for ( MapControlContainerToSetOfForms::const_iterator container = m_aNeedTabOrderUpdate.begin();
+ container != m_aNeedTabOrderUpdate.end();
+ ++container
+ )
+ {
+ FmWinRecList::iterator pos = findWindow( container->first );
+ if ( pos == m_aWinList.end() )
+ continue;
+
+ for ( SetOfForms::const_iterator form = container->second.begin();
+ form != container->second.end();
+ ++form
+ )
+ {
+ (*pos)->updateTabOrder( *form );
+ }
+ }
+ m_aNeedTabOrderUpdate.clear();
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FmXFormView, OnActivate, void*, /*EMPTYTAG*/)
+{
+ m_nActivationEvent = 0;
+
+ if ( !m_pView )
+ {
+ DBG_ERROR( "FmXFormView::OnActivate: well .... seems we have a timing problem (the view already died)!" );
+ return 0;
+ }
+
+ // setting the controller to activate
+ if (m_pView->GetFormShell() && m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
+ {
+ Window* pWindow = const_cast<Window*>(static_cast<const Window*>(m_pView->GetActualOutDev()));
+ FmXPageViewWinRec* pFmRec = m_aWinList.size() ? m_aWinList[0] : NULL;
+ for (FmWinRecList::const_iterator i = m_aWinList.begin();
+ i != m_aWinList.end(); ++i)
+ {
+ if (pWindow == (*i)->getWindow())
+ pFmRec =*i;
+ }
+
+ if (pFmRec)
+ {
+ for (::std::vector< Reference< XFormController > >::const_iterator i = pFmRec->GetList().begin();
+ i != pFmRec->GetList().end(); i++)
+ {
+ const Reference< XFormController > & xController = *i;
+ if (xController.is())
+ {
+ // Nur bei Datenbankformularen erfolgt eine aktivierung
+ Reference< XRowSet > xForm(xController->getModel(), UNO_QUERY);
+ if (xForm.is() && OStaticDataAccessTools().getRowSetConnection(xForm).is())
+ {
+ Reference< XPropertySet > xFormSet(xForm, UNO_QUERY);
+ if (xFormSet.is())
+ {
+ // wenn es eine Datenquelle gibt, dann als aktive ::com::sun::star::form setzen
+ ::rtl::OUString aSource = ::comphelper::getString(xFormSet->getPropertyValue(FM_PROP_COMMAND));
+ if (aSource.getLength())
+ {
+ // benachrichtigung der Shell
+ FmXFormShell* pShImpl = m_pView->GetFormShell()->GetImpl();
+ if (pShImpl)
+ pShImpl->setActiveController(xController);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::Activate(sal_Bool bSync)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::Activate" );
+ if (m_nActivationEvent)
+ {
+ Application::RemoveUserEvent(m_nActivationEvent);
+ m_nActivationEvent = 0;
+ }
+
+ if (bSync)
+ {
+ LINK(this,FmXFormView,OnActivate).Call(NULL);
+ }
+ else
+ m_nActivationEvent = Application::PostUserEvent(LINK(this,FmXFormView,OnActivate));
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::Deactivate(BOOL bDeactivateController)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::Deactivate" );
+ if (m_nActivationEvent)
+ {
+ Application::RemoveUserEvent(m_nActivationEvent);
+ m_nActivationEvent = 0;
+ }
+
+ FmXFormShell* pShImpl = m_pView->GetFormShell() ? m_pView->GetFormShell()->GetImpl() : NULL;
+ if (pShImpl && bDeactivateController)
+ pShImpl->setActiveController( NULL );
+}
+
+//------------------------------------------------------------------------------
+FmFormShell* FmXFormView::GetFormShell() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::GetFormShell" );
+ return m_pView ? m_pView->GetFormShell() : NULL;
+}
+// -----------------------------------------------------------------------------
+void FmXFormView::AutoFocus( sal_Bool _bSync )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::AutoFocus" );
+ if (m_nAutoFocusEvent)
+ Application::RemoveUserEvent(m_nAutoFocusEvent);
+
+ if ( _bSync )
+ OnAutoFocus( NULL );
+ else
+ m_nAutoFocusEvent = Application::PostUserEvent(LINK(this, FmXFormView, OnAutoFocus));
+}
+
+// -----------------------------------------------------------------------------
+bool FmXFormView::isFocusable( const Reference< XControl >& i_rControl )
+{
+ if ( !i_rControl.is() )
+ return false;
+
+ try
+ {
+ Reference< XPropertySet > xModelProps( i_rControl->getModel(), UNO_QUERY_THROW );
+
+ // only enabled controls are allowed to participate
+ sal_Bool bEnabled = sal_False;
+ OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_ENABLED ) >>= bEnabled );
+ if ( !bEnabled )
+ return false;
+
+ // check the class id of the control model
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+ OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
+
+ // controls which are not focussable
+ if ( ( FormComponentType::CONTROL != nClassId )
+ && ( FormComponentType::IMAGEBUTTON != nClassId )
+ && ( FormComponentType::GROUPBOX != nClassId )
+ && ( FormComponentType::FIXEDTEXT != nClassId )
+ && ( FormComponentType::HIDDENCONTROL != nClassId )
+ && ( FormComponentType::IMAGECONTROL != nClassId )
+ && ( FormComponentType::SCROLLBAR != nClassId )
+ && ( FormComponentType::SPINBUTTON!= nClassId )
+ )
+ {
+ return true;
+ }
+ }
+ catch( const Exception& e )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+static Reference< XControl > lcl_firstFocussableControl( const Sequence< Reference< XControl > >& _rControls )
+{
+ Reference< XControl > xReturn;
+
+ // loop through all the controls
+ const Reference< XControl >* pControls = _rControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = _rControls.getConstArray() + _rControls.getLength();
+ for ( ; pControls != pControlsEnd; ++pControls )
+ {
+ if ( !pControls->is() )
+ continue;
+
+ if ( FmXFormView::isFocusable( *pControls ) )
+ {
+ xReturn = *pControls;
+ break;
+ }
+ }
+
+ if ( !xReturn.is() && _rControls.getLength() )
+ xReturn = _rControls[0];
+
+ return xReturn;
+}
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ // .........................................................................
+ void lcl_ensureControlsOfFormExist_nothrow( const SdrPage& _rPage, const SdrView& _rView, const Window& _rWindow, const Reference< XForm >& _rxForm )
+ {
+ try
+ {
+ Reference< XInterface > xNormalizedForm( _rxForm, UNO_QUERY_THROW );
+
+ SdrObjListIter aSdrObjectLoop( _rPage, IM_DEEPNOGROUPS );
+ while ( aSdrObjectLoop.IsMore() )
+ {
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( aSdrObjectLoop.Next() );
+ if ( !pFormObject )
+ continue;
+
+ Reference< XChild > xModel( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
+ Reference< XInterface > xModelParent( xModel->getParent(), UNO_QUERY_THROW );
+
+ if ( xNormalizedForm.get() != xModelParent.get() )
+ continue;
+
+ pFormObject->GetUnoControl( _rView, _rWindow );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+Reference< XFormController > FmXFormView::getFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::getFormController" );
+ Reference< XFormController > xController;
+
+ for ( FmWinRecList::const_iterator rec = m_aWinList.begin(); rec != m_aWinList.end(); ++rec )
+ {
+ const FmXPageViewWinRec* pViewWinRec( *rec );
+ OSL_ENSURE( pViewWinRec, "FmXFormView::getFormController: invalid PageViewWinRec!" );
+ if ( !pViewWinRec || ( pViewWinRec->getWindow() != &_rDevice ) )
+ // wrong device
+ continue;
+
+ xController = pViewWinRec->getController( _rxForm );
+ if ( xController.is() )
+ break;
+ }
+ return xController;
+}
+
+// -----------------------------------------------------------------------------
+IMPL_LINK(FmXFormView, OnAutoFocus, void*, /*EMPTYTAG*/)
+{
+ m_nAutoFocusEvent = 0;
+
+ // go to the first form of our page, examine it's TabController, go to it's first (in terms of the tab order)
+ // control, give it the focus
+
+ do
+ {
+
+ // get the forms collection of the page we belong to
+ FmFormPage* pPage = m_pView ? PTR_CAST( FmFormPage, m_pView->GetSdrPageView()->GetPage() ) : NULL;
+ Reference< XIndexAccess > xForms( pPage ? Reference< XIndexAccess >( pPage->GetForms(), UNO_QUERY ) : Reference< XIndexAccess >() );
+
+ const FmXPageViewWinRec* pViewWinRec = m_aWinList.size() ? m_aWinList[0] : NULL;
+ const Window* pWindow = pViewWinRec ? pViewWinRec->getWindow() : NULL;
+
+ OSL_ENSURE( xForms.is() && pWindow, "FmXFormView::OnAutoFocus: could not collect all essentials!" );
+ if ( !xForms.is() || !pWindow )
+ return 0L;
+
+ try
+ {
+ // go for the tab controller of the first form
+ if ( !xForms->getCount() )
+ break;
+ Reference< XForm > xForm( xForms->getByIndex( 0 ), UNO_QUERY_THROW );
+ Reference< XTabController > xTabController( pViewWinRec->getController( xForm ), UNO_QUERY_THROW );
+
+ // go for the first control of the controller
+ Sequence< Reference< XControl > > aControls( xTabController->getControls() );
+ if ( aControls.getLength() == 0 )
+ {
+ Reference< XElementAccess > xFormElementAccess( xForm, UNO_QUERY_THROW );
+ if ( xFormElementAccess->hasElements() )
+ {
+ // there are control models in the form, but no controls, yet.
+ // Well, since some time controls are created on demand only. In particular,
+ // they're normally created when they're first painted.
+ // Unfortunately, the FormController does not have any way to
+ // trigger the creation itself, so we must hack this ...
+ lcl_ensureControlsOfFormExist_nothrow( *pPage, *m_pView, *pWindow, xForm );
+ aControls = xTabController->getControls();
+ OSL_ENSURE( aControls.getLength(), "FmXFormView::OnAutoFocus: no controls at all!" );
+ }
+ }
+
+ // set the focus to this first control
+ Reference< XWindow > xControlWindow( lcl_firstFocussableControl( aControls ), UNO_QUERY );
+ if ( !xControlWindow.is() )
+ break;
+
+ xControlWindow->setFocus();
+
+ // ensure that the control is visible
+ // 80210 - 12/07/00 - FS
+ const Window* pCurrentWindow = dynamic_cast< const Window* >( m_pView->GetActualOutDev() );
+ if ( pCurrentWindow )
+ {
+ awt::Rectangle aRect = xControlWindow->getPosSize();
+ ::Rectangle aNonUnoRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height );
+ m_pView->MakeVisible( pCurrentWindow->PixelToLogic( aNonUnoRect ), *const_cast< Window* >( pCurrentWindow ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ } // do
+ while ( false );
+
+ return 1L;
+}
+
+// -----------------------------------------------------------------------------
+void FmXFormView::onCreatedFormObject( FmFormObj& _rFormObject )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::onCreatedFormObject" );
+ FmFormShell* pShell = m_pView ? m_pView->GetFormShell() : NULL;
+ FmXFormShell* pShellImpl = pShell ? pShell->GetImpl() : NULL;
+ OSL_ENSURE( pShellImpl, "FmXFormView::onCreatedFormObject: no form shell!" );
+ if ( !pShellImpl )
+ return;
+
+ // it is valid that the form shell's forms collection is not initialized, yet
+ pShellImpl->UpdateForms( sal_True );
+
+ m_xLastCreatedControlModel.set( _rFormObject.GetUnoControlModel(), UNO_QUERY );
+ if ( !m_xLastCreatedControlModel.is() )
+ return;
+
+ // some initial property defaults
+ FormControlFactory aControlFactory( m_aContext );
+ aControlFactory.initializeControlModel( pShellImpl->getDocumentType(), _rFormObject );
+
+ if ( !pShellImpl->GetWizardUsing() )
+ return;
+
+ // #i31958# don't call wizards in XForms mode
+ if ( pShellImpl->isEnhancedForm() )
+ return;
+
+ // #i46898# no wizards if there is no Base installed - currently, all wizards are
+ // database related
+ if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
+ return;
+
+ if ( m_nControlWizardEvent )
+ Application::RemoveUserEvent( m_nControlWizardEvent );
+ m_nControlWizardEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnStartControlWizard ) );
+}
+
+// -----------------------------------------------------------------------------
+IMPL_LINK( FmXFormView, OnStartControlWizard, void*, /**/ )
+{
+ m_nControlWizardEvent = 0;
+ OSL_PRECOND( m_xLastCreatedControlModel.is(), "FmXFormView::OnStartControlWizard: illegal call!" );
+ if ( !m_xLastCreatedControlModel.is() )
+ return 0L;
+
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+ try
+ {
+ OSL_VERIFY( m_xLastCreatedControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ const sal_Char* pWizardAsciiName = NULL;
+ switch ( nClassId )
+ {
+ case FormComponentType::GRIDCONTROL:
+ pWizardAsciiName = "com.sun.star.sdb.GridControlAutoPilot";
+ break;
+ case FormComponentType::LISTBOX:
+ case FormComponentType::COMBOBOX:
+ pWizardAsciiName = "com.sun.star.sdb.ListComboBoxAutoPilot";
+ break;
+ case FormComponentType::GROUPBOX:
+ pWizardAsciiName = "com.sun.star.sdb.GroupBoxAutoPilot";
+ break;
+ }
+
+ if ( pWizardAsciiName )
+ {
+ // build the argument list
+ ::comphelper::NamedValueCollection aWizardArgs;
+ aWizardArgs.put( "ObjectModel", m_xLastCreatedControlModel );
+
+ // create the wizard object
+ Reference< XExecutableDialog > xWizard;
+ try
+ {
+ m_aContext.createComponentWithArguments( pWizardAsciiName, aWizardArgs.getWrappedPropertyValues(), xWizard );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ if ( !xWizard.is() )
+ {
+ ShowServiceNotAvailableError( NULL, String::CreateFromAscii( pWizardAsciiName ), sal_True );
+ }
+ else
+ {
+ // execute the wizard
+ try
+ {
+ xWizard->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+
+ m_xLastCreatedControlModel.clear();
+ return 1L;
+}
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ void lcl_insertIntoFormComponentHierarchy_throw( const FmFormView& _rView, const SdrUnoObj& _rSdrObj,
+ const Reference< XDataSource >& _rxDataSource = NULL, const ::rtl::OUString& _rDataSourceName = ::rtl::OUString(),
+ const ::rtl::OUString& _rCommand = ::rtl::OUString(), const sal_Int32 _nCommandType = -1 )
+ {
+ FmFormPage& rPage = static_cast< FmFormPage& >( *_rView.GetSdrPageView()->GetPage() );
+
+ Reference< XFormComponent > xFormComponent( _rSdrObj.GetUnoControlModel(), UNO_QUERY_THROW );
+ Reference< XForm > xTargetForm(
+ rPage.GetImpl().findPlaceInFormComponentHierarchy( xFormComponent, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType ),
+ UNO_SET_THROW );
+
+ rPage.GetImpl().setUniqueName( xFormComponent, xTargetForm );
+
+ Reference< XIndexContainer > xFormAsContainer( xTargetForm, UNO_QUERY_THROW );
+ xFormAsContainer->insertByIndex( xFormAsContainer->getCount(), makeAny( xFormComponent ) );
+ }
+}
+
+// -----------------------------------------------------------------------------
+SdrObject* FmXFormView::implCreateFieldControl( const ::svx::ODataAccessDescriptor& _rColumnDescriptor )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::implCreateFieldControl" );
+ // not if we're in design mode
+ if ( !m_pView->IsDesignMode() )
+ return NULL;
+
+ ::rtl::OUString sCommand, sFieldName;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ SharedConnection xConnection;
+
+ ::rtl::OUString sDataSource = _rColumnDescriptor.getDataSource();
+ _rColumnDescriptor[ daCommand ] >>= sCommand;
+ _rColumnDescriptor[ daColumnName ] >>= sFieldName;
+ _rColumnDescriptor[ daCommandType ] >>= nCommandType;
+ {
+ Reference< XConnection > xExternalConnection;
+ _rColumnDescriptor[ daConnection ] >>= xExternalConnection;
+ xConnection.reset( xExternalConnection, SharedConnection::NoTakeOwnership );
+ }
+
+ if ( !sCommand.getLength()
+ || !sFieldName.getLength()
+ || ( !sDataSource.getLength()
+ && !xConnection.is()
+ )
+ )
+ {
+ DBG_ERROR( "FmXFormView::implCreateFieldControl: nonsense!" );
+ }
+
+ Reference< XDataSource > xDataSource;
+ SQLErrorEvent aError;
+ try
+ {
+ if ( xConnection.is() && !xDataSource.is() && !sDataSource.getLength() )
+ {
+ Reference< XChild > xChild( xConnection, UNO_QUERY );
+ if ( xChild.is() )
+ xDataSource = xDataSource.query( xChild->getParent() );
+ }
+
+ // obtain the data source
+ if ( !xDataSource.is() )
+ xDataSource = OStaticDataAccessTools().getDataSource( sDataSource, m_aContext.getLegacyServiceFactory() );
+
+ // and the connection, if necessary
+ if ( !xConnection.is() )
+ xConnection.reset( OStaticDataAccessTools().getConnection_withFeedback(
+ sDataSource,
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ m_aContext.getLegacyServiceFactory()
+ ) );
+ }
+ catch ( const SQLException& )
+ {
+ aError.Reason = ::cppu::getCaughtException();
+ }
+ catch( const Exception& ) { /* will be asserted below */ }
+ if (aError.Reason.hasValue())
+ {
+ displayAsyncErrorMessage( aError );
+ return NULL;
+ }
+
+ // need a data source and a connection here
+ if (!xDataSource.is() || !xConnection.is())
+ {
+ DBG_ERROR("FmXFormView::implCreateFieldControl : could not retrieve the data source or the connection!");
+ return NULL;
+ }
+
+ OStaticDataAccessTools aDBATools;
+ Reference< XComponent > xKeepFieldsAlive;
+ // go
+ try
+ {
+ // determine the table/query field which we should create a control for
+ Reference< XPropertySet > xField;
+
+ Reference< XNameAccess > xFields = aDBATools.getFieldsByCommandDescriptor(
+ xConnection, nCommandType, sCommand, xKeepFieldsAlive );
+
+ if (xFields.is() && xFields->hasByName(sFieldName))
+ xFields->getByName(sFieldName) >>= xField;
+ if ( !xField.is() )
+ return NULL;
+
+ Reference< XNumberFormatsSupplier > xSupplier( aDBATools.getNumberFormats( xConnection, sal_False ), UNO_SET_THROW );
+ Reference< XNumberFormats > xNumberFormats( xSupplier->getNumberFormats(), UNO_SET_THROW );
+
+ ::rtl::OUString sLabelPostfix;
+
+ ////////////////////////////////////////////////////////////////
+ // nur fuer Textgroesse
+ OutputDevice* pOutDev = NULL;
+ if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
+ pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev());
+ else
+ {// OutDev suchen
+ SdrPageView* pPageView = m_pView->GetSdrPageView();
+ if( pPageView && !pOutDev )
+ {
+ // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
+ // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
+
+ for( sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); i++ )
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
+
+ if( rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice();
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !pOutDev )
+ return NULL;
+
+ sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE));
+ if ((DataType::BINARY == nDataType) || (DataType::VARBINARY == nDataType))
+ return NULL;
+
+ //////////////////////////////////////////////////////////////////////
+ // determine the control type by examining the data type of the bound column
+ sal_uInt16 nOBJID = 0;
+ sal_Bool bDateNTimeField = sal_False;
+
+ sal_Bool bIsCurrency = sal_False;
+ if (::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField))
+ bIsCurrency = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY));
+
+ if (bIsCurrency)
+ nOBJID = OBJ_FM_CURRENCYFIELD;
+ else
+ switch (nDataType)
+ {
+ case DataType::BLOB:
+ case DataType::LONGVARBINARY:
+ nOBJID = OBJ_FM_IMAGECONTROL;
+ break;
+ case DataType::LONGVARCHAR:
+ case DataType::CLOB:
+ nOBJID = OBJ_FM_EDIT;
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ return NULL;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ nOBJID = OBJ_FM_CHECKBOX;
+ break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ nOBJID = OBJ_FM_NUMERICFIELD;
+ break;
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ nOBJID = OBJ_FM_FORMATTEDFIELD;
+ break;
+ case DataType::TIMESTAMP:
+ bDateNTimeField = sal_True;
+ sLabelPostfix = String( SVX_RES( RID_STR_POSTFIX_DATE ) );
+ // DON'T break !
+ case DataType::DATE:
+ nOBJID = OBJ_FM_DATEFIELD;
+ break;
+ case DataType::TIME:
+ nOBJID = OBJ_FM_TIMEFIELD;
+ break;
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ default:
+ nOBJID = OBJ_FM_EDIT;
+ break;
+ }
+ if (!nOBJID)
+ return NULL;
+
+ SdrUnoObj* pLabel( NULL );
+ SdrUnoObj* pControl( NULL );
+ if ( !createControlLabelPair( *pOutDev, 0, 0, xField, xNumberFormats, nOBJID, sLabelPostfix,
+ pLabel, pControl, xDataSource, sDataSource, sCommand, nCommandType )
+ )
+ {
+ return NULL;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // group objects
+ bool bCheckbox = ( OBJ_FM_CHECKBOX == nOBJID );
+ OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateFieldControl: why was there a label created for a check box?" );
+ if ( bCheckbox )
+ return pControl;
+
+ SdrObjGroup* pGroup = new SdrObjGroup();
+ SdrObjList* pObjList = pGroup->GetSubList();
+ pObjList->InsertObject( pLabel );
+ pObjList->InsertObject( pControl );
+
+ if ( bDateNTimeField )
+ { // so far we created a date field only, but we also need a time field
+ pLabel = pControl = NULL;
+ if ( createControlLabelPair( *pOutDev, 0, 1000, xField, xNumberFormats, OBJ_FM_TIMEFIELD,
+ String( SVX_RES( RID_STR_POSTFIX_TIME ) ), pLabel, pControl,
+ xDataSource, sDataSource, sCommand, nCommandType )
+ )
+ {
+ pObjList->InsertObject( pLabel );
+ pObjList->InsertObject( pControl );
+ }
+ }
+
+ return pGroup; // und fertig
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------------
+SdrObject* FmXFormView::implCreateXFormsControl( const ::svx::OXFormsDescriptor &_rDesc )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::implCreateXFormsControl" );
+ // not if we're in design mode
+ if ( !m_pView->IsDesignMode() )
+ return NULL;
+
+ Reference< XComponent > xKeepFieldsAlive;
+
+ // go
+ try
+ {
+ // determine the table/query field which we should create a control for
+ Reference< XNumberFormats > xNumberFormats;
+ ::rtl::OUString sLabelPostfix = _rDesc.szName;
+
+ ////////////////////////////////////////////////////////////////
+ // nur fuer Textgroesse
+ OutputDevice* pOutDev = NULL;
+ if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
+ pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev());
+ else
+ {// OutDev suchen
+ SdrPageView* pPageView = m_pView->GetSdrPageView();
+ if( pPageView && !pOutDev )
+ {
+ // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
+ // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
+
+ for( sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); i++ )
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
+
+ if( rPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType() == OUTDEV_WINDOW)
+ {
+ pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice();
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !pOutDev )
+ return NULL;
+
+ //////////////////////////////////////////////////////////////////////
+ // The service name decides which control should be created
+ sal_uInt16 nOBJID = OBJ_FM_EDIT;
+ if(::rtl::OUString(_rDesc.szServiceName).equals((::rtl::OUString)FM_SUN_COMPONENT_NUMERICFIELD))
+ nOBJID = OBJ_FM_NUMERICFIELD;
+ if(::rtl::OUString(_rDesc.szServiceName).equals((::rtl::OUString)FM_SUN_COMPONENT_CHECKBOX))
+ nOBJID = OBJ_FM_CHECKBOX;
+ if(::rtl::OUString(_rDesc.szServiceName).equals((::rtl::OUString)FM_COMPONENT_COMMANDBUTTON))
+ nOBJID = OBJ_FM_BUTTON;
+
+ typedef ::com::sun::star::form::submission::XSubmission XSubmission_t;
+ Reference< XSubmission_t > xSubmission(_rDesc.xPropSet, UNO_QUERY);
+
+ // xform control or submission button?
+ if ( !xSubmission.is() )
+ {
+ SdrUnoObj* pLabel( NULL );
+ SdrUnoObj* pControl( NULL );
+ if ( !createControlLabelPair( *pOutDev, 0, 0, NULL, xNumberFormats, nOBJID, sLabelPostfix,
+ pLabel, pControl )
+ )
+ {
+ return NULL;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Now build the connection between the control and the data item.
+ Reference< XValueBinding > xValueBinding(_rDesc.xPropSet,UNO_QUERY);
+ Reference< XBindableValue > xBindableValue(pControl->GetUnoControlModel(),UNO_QUERY);
+
+ DBG_ASSERT( xBindableValue.is(), "FmXFormView::implCreateXFormsControl: control's not bindable!" );
+ if ( xBindableValue.is() )
+ xBindableValue->setValueBinding(xValueBinding);
+
+ bool bCheckbox = ( OBJ_FM_CHECKBOX == nOBJID );
+ OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateXFormsControl: why was there a label created for a check box?" );
+ if ( bCheckbox )
+ return pControl;
+
+ //////////////////////////////////////////////////////////////////////
+ // group objects
+ SdrObjGroup* pGroup = new SdrObjGroup();
+ SdrObjList* pObjList = pGroup->GetSubList();
+ pObjList->InsertObject(pLabel);
+ pObjList->InsertObject(pControl);
+
+ return pGroup;
+ }
+ else {
+
+ // create a button control
+ const MapMode eTargetMode( pOutDev->GetMapMode() );
+ const MapMode eSourceMode(MAP_100TH_MM);
+ const sal_uInt16 nObjID = OBJ_FM_BUTTON;
+ ::Size controlSize(4000, 500);
+ FmFormObj *pControl = static_cast<FmFormObj*>(SdrObjFactory::MakeNewObject( FmFormInventor, nObjID, NULL, NULL ));
+ controlSize.Width() = Fraction(controlSize.Width(), 1) * eTargetMode.GetScaleX();
+ controlSize.Height() = Fraction(controlSize.Height(), 1) * eTargetMode.GetScaleY();
+ ::Point controlPos( pOutDev->LogicToLogic( ::Point( controlSize.Width(), 0 ), eSourceMode, eTargetMode ) );
+ ::Rectangle controlRect( controlPos, pOutDev->LogicToLogic( controlSize, eSourceMode, eTargetMode ) );
+ pControl->SetLogicRect(controlRect);
+
+ // set the button label
+ Reference< XPropertySet > xControlSet(pControl->GetUnoControlModel(), UNO_QUERY);
+ xControlSet->setPropertyValue(FM_PROP_LABEL, makeAny(::rtl::OUString(_rDesc.szName)));
+
+ // connect the submission with the submission supplier (aka the button)
+ xControlSet->setPropertyValue( FM_PROP_BUTTON_TYPE,
+ makeAny( FormButtonType_SUBMIT ) );
+ typedef ::com::sun::star::form::submission::XSubmissionSupplier XSubmissionSupplier_t;
+ Reference< XSubmissionSupplier_t > xSubmissionSupplier(pControl->GetUnoControlModel(), UNO_QUERY);
+ xSubmissionSupplier->setSubmission(xSubmission);
+
+ return pControl;
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_ERROR("FmXFormView::implCreateXFormsControl: caught an exception while creating the control !");
+ }
+
+
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+bool FmXFormView::createControlLabelPair( OutputDevice& _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
+ const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats,
+ sal_uInt16 _nControlObjectID, const ::rtl::OUString& _rFieldPostfix,
+ SdrUnoObj*& _rpLabel, SdrUnoObj*& _rpControl,
+ const Reference< XDataSource >& _rxDataSource, const ::rtl::OUString& _rDataSourceName,
+ const ::rtl::OUString& _rCommand, const sal_Int32 _nCommandType )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::createControlLabelPair" );
+ if ( !createControlLabelPair( m_aContext, _rOutDev, _nXOffsetMM, _nYOffsetMM,
+ _rxField, _rxNumberFormats, _nControlObjectID, _rFieldPostfix, FmFormInventor, OBJ_FM_FIXEDTEXT,
+ NULL, NULL, NULL, _rpLabel, _rpControl )
+ )
+ return false;
+
+ // insert the control model(s) into the form component hierachy
+ if ( _rpLabel )
+ lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpLabel, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType );
+ lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpControl, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType );
+
+ // some context-dependent initializations
+ FormControlFactory aControlFactory( m_aContext );
+ if ( _rpLabel )
+ aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpLabel );
+ aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpControl );
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FmXFormView::createControlLabelPair( const ::comphelper::ComponentContext& _rContext,
+ OutputDevice& _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM, const Reference< XPropertySet >& _rxField,
+ const Reference< XNumberFormats >& _rxNumberFormats, sal_uInt16 _nControlObjectID,
+ const ::rtl::OUString& _rFieldPostfix, UINT32 _nInventor, UINT16 _nLabelObjectID,
+ SdrPage* _pLabelPage, SdrPage* _pControlPage, SdrModel* _pModel, SdrUnoObj*& _rpLabel, SdrUnoObj*& _rpControl)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::createControlLabelPair" );
+ sal_Int32 nDataType = 0;
+ ::rtl::OUString sFieldName;
+ Any aFieldName;
+ if ( _rxField.is() )
+ {
+ nDataType = ::comphelper::getINT32(_rxField->getPropertyValue(FM_PROP_FIELDTYPE));
+ aFieldName = Any(_rxField->getPropertyValue(FM_PROP_NAME));
+ aFieldName >>= sFieldName;
+ }
+
+ // calculate the positions, respecting the settings of the target device
+ ::Size aTextSize( _rOutDev.GetTextWidth(sFieldName + _rFieldPostfix), _rOutDev.GetTextHeight() );
+
+ MapMode eTargetMode( _rOutDev.GetMapMode() ),
+ eSourceMode( MAP_100TH_MM );
+
+ // Textbreite ist mindestens 4cm
+ // Texthoehe immer halber cm
+ ::Size aDefTxtSize(4000, 500);
+ ::Size aDefSize(4000, 500);
+ ::Size aDefImageSize(4000, 4000);
+
+ ::Size aRealSize = _rOutDev.LogicToLogic(aTextSize, eTargetMode, eSourceMode);
+ aRealSize.Width() = std::max(aRealSize.Width(), aDefTxtSize.Width());
+ aRealSize.Height()= aDefSize.Height();
+
+ // adjust to scaling of the target device (#53523#)
+ aRealSize.Width() = long(Fraction(aRealSize.Width(), 1) * eTargetMode.GetScaleX());
+ aRealSize.Height() = long(Fraction(aRealSize.Height(), 1) * eTargetMode.GetScaleY());
+
+ // for boolean fields, we do not create a label, but just a checkbox
+ bool bNeedLabel = ( _nControlObjectID != OBJ_FM_CHECKBOX );
+
+ // the label
+ ::std::auto_ptr< SdrUnoObj > pLabel;
+ Reference< XPropertySet > xLabelModel;
+ if ( bNeedLabel )
+ {
+ pLabel.reset( dynamic_cast< SdrUnoObj* >(
+ SdrObjFactory::MakeNewObject( _nInventor, _nLabelObjectID, _pLabelPage, _pModel ) ) );
+ OSL_ENSURE( pLabel.get(), "FmXFormView::createControlLabelPair: could not create the label!" );
+ if ( !pLabel.get() )
+ return false;
+
+ xLabelModel.set( pLabel->GetUnoControlModel(), UNO_QUERY );
+ if ( xLabelModel.is() )
+ {
+ ::rtl::OUString sLabel;
+ if ( _rxField.is() && _rxField->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) )
+ _rxField->getPropertyValue(FM_PROP_LABEL) >>= sLabel;
+ if ( !sLabel.getLength() )
+ sLabel = sFieldName;
+
+ xLabelModel->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel + _rFieldPostfix ) );
+ String sObjectLabel( SVX_RES( RID_STR_OBJECT_LABEL ) );
+ sObjectLabel.SearchAndReplaceAllAscii( "#object#", sFieldName );
+ xLabelModel->setPropertyValue( FM_PROP_NAME, makeAny( ::rtl::OUString( sObjectLabel ) ) );
+ }
+
+ pLabel->SetLogicRect( ::Rectangle(
+ _rOutDev.LogicToLogic( ::Point( _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ),
+ _rOutDev.LogicToLogic( aRealSize, eSourceMode, eTargetMode )
+ ) );
+ }
+
+ // the control
+ ::std::auto_ptr< SdrUnoObj > pControl( dynamic_cast< SdrUnoObj* >(
+ SdrObjFactory::MakeNewObject( _nInventor, _nControlObjectID, _pControlPage, _pModel ) ) );
+ OSL_ENSURE( pControl.get(), "FmXFormView::createControlLabelPair: could not create the control!" );
+ if ( !pControl.get() )
+ return false;
+
+ Reference< XPropertySet > xControlSet( pControl->GetUnoControlModel(), UNO_QUERY );
+ if ( !xControlSet.is() )
+ return false;
+
+ // size of the control
+ ::Size aControlSize( aDefSize );
+ switch ( nDataType )
+ {
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ aControlSize = aDefSize;
+ break;
+ case DataType::LONGVARCHAR:
+ case DataType::CLOB:
+ case DataType::LONGVARBINARY:
+ case DataType::BLOB:
+ aControlSize = aDefImageSize;
+ break;
+ }
+
+ if ( OBJ_FM_IMAGECONTROL == _nControlObjectID )
+ aControlSize = aDefImageSize;
+
+ aControlSize.Width() = long(Fraction(aControlSize.Width(), 1) * eTargetMode.GetScaleX());
+ aControlSize.Height() = long(Fraction(aControlSize.Height(), 1) * eTargetMode.GetScaleY());
+
+ pControl->SetLogicRect( ::Rectangle(
+ _rOutDev.LogicToLogic( ::Point( aRealSize.Width() + _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ),
+ _rOutDev.LogicToLogic( aControlSize, eSourceMode, eTargetMode )
+ ) );
+
+ // some initializations
+ Reference< XPropertySetInfo > xControlPropInfo = xControlSet->getPropertySetInfo();
+
+ if ( aFieldName.hasValue() )
+ {
+ xControlSet->setPropertyValue( FM_PROP_CONTROLSOURCE, aFieldName );
+ xControlSet->setPropertyValue( FM_PROP_NAME, aFieldName );
+ if ( !bNeedLabel )
+ {
+ // no dedicated label control => use the label property
+ if ( xControlPropInfo->hasPropertyByName( FM_PROP_LABEL ) )
+ xControlSet->setPropertyValue( FM_PROP_LABEL, makeAny( sFieldName + _rFieldPostfix ) );
+ else
+ OSL_ENSURE( false, "FmXFormView::createControlLabelPair: can't set a label for the control!" );
+ }
+ }
+
+ if ( (nDataType == DataType::LONGVARCHAR || nDataType == DataType::CLOB) && xControlPropInfo->hasPropertyByName( FM_PROP_MULTILINE ) )
+ {
+ xControlSet->setPropertyValue( FM_PROP_MULTILINE, makeAny( sal_Bool( sal_True ) ) );
+ }
+
+ // announce the label to the control
+ if ( xControlPropInfo->hasPropertyByName( FM_PROP_CONTROLLABEL ) && xLabelModel.is() )
+ {
+ try
+ {
+ xControlSet->setPropertyValue( FM_PROP_CONTROLLABEL, makeAny( xLabelModel ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ if ( _rxField.is() )
+ {
+ FormControlFactory aControlFactory( _rContext );
+ aControlFactory.initializeFieldDependentProperties( _rxField, xControlSet, _rxNumberFormats );
+ }
+
+ _rpLabel = pLabel.release();
+ _rpControl = pControl.release();
+ return true;
+}
+
+//------------------------------------------------------------------------------
+FmXFormView::ObjectRemoveListener::ObjectRemoveListener( FmXFormView* pParent )
+ :m_pParent( pParent )
+{
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::ObjectRemoveListener::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ if (rHint.ISA(SdrHint) && (((SdrHint&)rHint).GetKind() == HINT_OBJREMOVED))
+ m_pParent->ObjectRemovedInAliveMode(((SdrHint&)rHint).GetObject());
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::ObjectRemovedInAliveMode( const SdrObject* pObject )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::ObjectRemovedInAliveMode" );
+ // wenn das entfernte Objekt in meiner MarkList, die ich mir beim Umschalten in den Alive-Mode gemerkt habe, steht,
+ // muss ich es jetzt da rausnehmen, da ich sonst beim Zurueckschalten versuche, die Markierung wieder zu setzen
+ // (interesanterweise geht das nur bei gruppierten Objekten schief (beim Zugriff auf deren ObjList GPF), nicht bei einzelnen)
+
+ ULONG nCount = m_aMark.GetMarkCount();
+ for (ULONG i = 0; i < nCount; ++i)
+ {
+ SdrMark* pMark = m_aMark.GetMark(i);
+ SdrObject* pCurrent = pMark->GetMarkedSdrObj();
+ if (pObject == pCurrent)
+ {
+ m_aMark.DeleteMark(i);
+ return;
+ }
+ // ich brauche nicht in GroupObjects absteigen : wenn dort unten ein Objekt geloescht wird, dann bleibt der
+ // Zeiger auf das GroupObject, den ich habe, trotzdem weiter gueltig bleibt ...
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::stopMarkListWatching()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::stopMarkListWatching" );
+ if ( m_pWatchStoredList )
+ {
+ m_pWatchStoredList->EndListeningAll();
+ delete m_pWatchStoredList;
+ m_pWatchStoredList = NULL;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::startMarkListWatching()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::startMarkListWatching" );
+ if ( !m_pWatchStoredList )
+ {
+ m_pWatchStoredList = new ObjectRemoveListener( this );
+ FmFormModel* pModel = GetFormShell() ? GetFormShell()->GetFormModel() : NULL;
+ DBG_ASSERT( pModel != NULL, "FmXFormView::startMarkListWatching: shell has no model!" );
+ m_pWatchStoredList->StartListening( *static_cast< SfxBroadcaster* >( pModel ) );
+ }
+ else
+ {
+ DBG_ERROR( "FmXFormView::startMarkListWatching: already listening!" );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::saveMarkList( sal_Bool _bSmartUnmark )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::saveMarkList" );
+ if ( m_pView )
+ {
+ m_aMark = m_pView->GetMarkedObjectList();
+ if ( _bSmartUnmark )
+ {
+ ULONG nCount = m_aMark.GetMarkCount( );
+ for ( ULONG i = 0; i < nCount; ++i )
+ {
+ SdrMark* pMark = m_aMark.GetMark(i);
+ SdrObject* pObj = pMark->GetMarkedSdrObj();
+
+ if ( m_pView->IsObjMarked( pObj ) )
+ {
+ if ( pObj->IsGroupObject() )
+ {
+ SdrObjListIter aIter( *pObj->GetSubList() );
+ sal_Bool bMixed = sal_False;
+ while ( aIter.IsMore() && !bMixed )
+ bMixed = ( aIter.Next()->GetObjInventor() != FmFormInventor );
+
+ if ( !bMixed )
+ {
+ // all objects in the group are form objects
+ m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), sal_True /* unmark! */ );
+ }
+ }
+ else
+ {
+ if ( pObj->GetObjInventor() == FmFormInventor )
+ { // this is a form layer object
+ m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), sal_True /* unmark! */ );
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DBG_ERROR( "FmXFormView::saveMarkList: invalid view!" );
+ m_aMark = SdrMarkList();
+ }
+}
+
+//--------------------------------------------------------------------------
+static sal_Bool lcl_hasObject( SdrObjListIter& rIter, SdrObject* pObj )
+{
+ sal_Bool bFound = sal_False;
+ while (rIter.IsMore() && !bFound)
+ bFound = pObj == rIter.Next();
+
+ rIter.Reset();
+ return bFound;
+}
+
+//------------------------------------------------------------------------------
+void FmXFormView::restoreMarkList( SdrMarkList& _rRestoredMarkList )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::restoreMarkList" );
+ if ( !m_pView )
+ return;
+
+ _rRestoredMarkList.Clear();
+
+ const SdrMarkList& rCurrentList = m_pView->GetMarkedObjectList();
+ FmFormPage* pPage = GetFormShell() ? GetFormShell()->GetCurPage() : NULL;
+ if (pPage)
+ {
+ if (rCurrentList.GetMarkCount())
+ { // there is a current mark ... hmm. Is it a subset of the mark we remembered in saveMarkList?
+ sal_Bool bMisMatch = sal_False;
+
+ // loop through all current marks
+ ULONG nCurrentCount = rCurrentList.GetMarkCount();
+ for ( ULONG i=0; i<nCurrentCount&& !bMisMatch; ++i )
+ {
+ const SdrObject* pCurrentMarked = rCurrentList.GetMark( i )->GetMarkedSdrObj();
+
+ // loop through all saved marks, check for equality
+ sal_Bool bFound = sal_False;
+ ULONG nSavedCount = m_aMark.GetMarkCount();
+ for ( ULONG j=0; j<nSavedCount && !bFound; ++j )
+ {
+ if ( m_aMark.GetMark( j )->GetMarkedSdrObj() == pCurrentMarked )
+ bFound = sal_True;
+ }
+
+ // did not find a current mark in the saved marks
+ if ( !bFound )
+ bMisMatch = sal_True;
+ }
+
+ if ( bMisMatch )
+ {
+ m_aMark.Clear();
+ _rRestoredMarkList = rCurrentList;
+ return;
+ }
+ }
+ // wichtig ist das auf die Objecte der markliste nicht zugegriffen wird
+ // da diese bereits zerstoert sein koennen
+ SdrPageView* pCurPageView = m_pView->GetSdrPageView();
+ SdrObjListIter aPageIter( *pPage );
+ sal_Bool bFound = sal_True;
+
+ // gibt es noch alle Objecte
+ ULONG nCount = m_aMark.GetMarkCount();
+ for (ULONG i = 0; i < nCount && bFound; i++)
+ {
+ SdrMark* pMark = m_aMark.GetMark(i);
+ SdrObject* pObj = pMark->GetMarkedSdrObj();
+ if (pObj->IsGroupObject())
+ {
+ SdrObjListIter aIter(*pObj->GetSubList());
+ while (aIter.IsMore() && bFound)
+ bFound = lcl_hasObject(aPageIter, aIter.Next());
+ }
+ else
+ bFound = lcl_hasObject(aPageIter, pObj);
+
+ bFound = bFound && pCurPageView == pMark->GetPageView();
+ }
+
+ if (bFound)
+ {
+ // Das LastObject auswerten
+ if (nCount) // Objecte jetzt Markieren
+ {
+ for (ULONG i = 0; i < nCount; i++)
+ {
+ SdrMark* pMark = m_aMark.GetMark(i);
+ SdrObject* pObj = pMark->GetMarkedSdrObj();
+ if ( pObj->GetObjInventor() == FmFormInventor )
+ if ( !m_pView->IsObjMarked( pObj ) )
+ m_pView->MarkObj( pObj, pMark->GetPageView() );
+ }
+
+ _rRestoredMarkList = m_aMark;
+ }
+ }
+ m_aMark.Clear();
+ }
+}
+// -----------------------------------------------------------------------------
+void SAL_CALL FmXFormView::focusGained( const FocusEvent& /*e*/ ) throw (RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::focusGained" );
+ if ( m_xWindow.is() && m_pView )
+ {
+ m_pView->SetMoveOutside( TRUE, FmFormView::ImplAccess() );
+ }
+}
+// -----------------------------------------------------------------------------
+void SAL_CALL FmXFormView::focusLost( const FocusEvent& /*e*/ ) throw (RuntimeException)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::focusLost" );
+ // when switch the focus outside the office the mark didn't change
+ // so we can not remove us as focus listener
+ if ( m_xWindow.is() && m_pView )
+ {
+ m_pView->SetMoveOutside( FALSE, FmFormView::ImplAccess() );
+ }
+}
+// -----------------------------------------------------------------------------
+void FmXFormView::removeGridWindowListening()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::removeGridWindowListening" );
+ if ( m_xWindow.is() )
+ {
+ m_xWindow->removeFocusListener(this);
+ if ( m_pView )
+ {
+ m_pView->SetMoveOutside( FALSE, FmFormView::ImplAccess() );
+ }
+ m_xWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------------
+DocumentType FmXFormView::impl_getDocumentType() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXFormView::impl_getDocumentType" );
+ if ( GetFormShell() && GetFormShell()->GetImpl() )
+ return GetFormShell()->GetImpl()->getDocumentType();
+ return eUnknownDocumentType;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formcontrolfactory.cxx b/svx/source/form/formcontrolfactory.cxx
new file mode 100644
index 000000000000..bb3f5c2b164f
--- /dev/null
+++ b/svx/source/form/formcontrolfactory.cxx
@@ -0,0 +1,736 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "svx/dbtoolsclient.hxx"
+#include "formcontrolfactory.hxx"
+#include "fmcontrollayout.hxx"
+#include "fmprop.hrc"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "svx/dialmgr.hxx"
+#include "svx/svdouno.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/awt/MouseWheelBehavior.hpp>
+#include <com/sun/star/form/XGridColumnFactory.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/awt/LineEndFormat.hpp>
+#include <com/sun/star/awt/ImageScaleMode.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/numbers.hxx>
+#include <unotools/syslocale.hxx>
+#include <tools/gen.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <set>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::awt::XControlModel;
+ using ::com::sun::star::form::XFormComponent;
+ using ::com::sun::star::container::XIndexAccess;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::form::XGridColumnFactory;
+ using ::com::sun::star::style::VerticalAlignment_MIDDLE;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::uno::TypeClass_DOUBLE;
+ using ::com::sun::star::uno::TypeClass_LONG;
+ using ::com::sun::star::util::XNumberFormats;
+ using ::com::sun::star::util::XNumberFormatTypes;
+ using ::com::sun::star::awt::FontDescriptor;
+ using ::com::sun::star::lang::Locale;
+ using ::com::sun::star::lang::XServiceInfo;
+ using ::com::sun::star::container::XNameAccess;
+ /** === end UNO using === **/
+ namespace FormComponentType = ::com::sun::star::form::FormComponentType;
+ namespace ScrollBarOrientation = ::com::sun::star::awt::ScrollBarOrientation;
+ namespace MouseWheelBehavior = ::com::sun::star::awt::MouseWheelBehavior;
+ namespace LineEndFormat = ::com::sun::star::awt::LineEndFormat;
+ namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
+ namespace DataType = ::com::sun::star::sdbc::DataType;
+ namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
+ namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
+
+ //====================================================================
+ //= FormControlFactory_Data
+ //====================================================================
+ struct FormControlFactory_Data
+ {
+ ::comphelper::ComponentContext m_aContext;
+
+ FormControlFactory_Data( const ::comphelper::ComponentContext& _rContext )
+ :m_aContext( _rContext )
+ {
+ }
+ };
+
+ //====================================================================
+ //= FormControlFactory
+ //====================================================================
+ //--------------------------------------------------------------------
+ FormControlFactory::FormControlFactory( const ::comphelper::ComponentContext& _rContext )
+ :m_pData( new FormControlFactory_Data( _rContext ) )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ FormControlFactory::~FormControlFactory()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const SdrUnoObj& _rObject )
+ {
+ return initializeControlModel(
+ _eDocType,
+ Reference< XPropertySet >( _rObject.GetUnoControlModel(), UNO_QUERY ),
+ _rObject.GetCurrentBoundRect()
+ );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel )
+ {
+ return initializeControlModel(
+ _eDocType, _rxControlModel, Rectangle()
+ );
+ }
+
+ // -----------------------------------------------------------------------------
+ namespace
+ {
+ //....................................................................
+ static ::rtl::OUString lcl_getUniqueLabel_nothrow( const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rBaseLabel )
+ {
+ ::rtl::OUString sLabel( _rBaseLabel );
+ try
+ {
+ typedef ::std::set< ::rtl::OUString > StringBag;
+ StringBag aUsedLabels;
+
+ Reference< XFormComponent > xFormComponent( _rxControlModel, UNO_QUERY_THROW );
+ Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
+ // loop through all siblings of the control model, and collect their labels
+ for ( sal_Int32 index=xContainer->getCount(); index>0; )
+ {
+ Reference< XPropertySet > xElement( xContainer->getByIndex( --index ), UNO_QUERY_THROW );
+ if ( xElement == _rxControlModel )
+ continue;
+
+ Reference< XPropertySetInfo > xPSI( xElement->getPropertySetInfo(), UNO_SET_THROW );
+ if ( !xPSI->hasPropertyByName( FM_PROP_LABEL ) )
+ continue;
+
+ ::rtl::OUString sElementLabel;
+ OSL_VERIFY( xElement->getPropertyValue( FM_PROP_LABEL ) >>= sElementLabel );
+ aUsedLabels.insert( sElementLabel );
+ }
+
+ // now find a free label
+ sal_Int32 i=2;
+ while ( aUsedLabels.find( sLabel ) != aUsedLabels.end() )
+ {
+ ::rtl::OUStringBuffer aBuffer( _rBaseLabel );
+ aBuffer.appendAscii( " " );
+ aBuffer.append( (sal_Int32)i++ );
+ sLabel = aBuffer.makeStringAndClear();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return sLabel;
+ }
+
+ //....................................................................
+ static Sequence< PropertyValue > lcl_getDataSourceIndirectProperties( const Reference< XPropertySet >& _rxControlModel,
+ const ::comphelper::ComponentContext& _rContext )
+ {
+ OSL_PRECOND( _rxControlModel.is(), "lcl_getDataSourceIndirectProperties: invalid model!" );
+
+ Sequence< PropertyValue > aInfo;
+ try
+ {
+ Reference< XChild > xChild( _rxControlModel, UNO_QUERY );
+ Reference< XPropertySet > xForm;
+ if ( xChild.is() )
+ xForm = xForm.query( xChild->getParent() );
+
+ if ( Reference< XGridColumnFactory >( xForm, UNO_QUERY ).is() )
+ { // hmm. the model is a grid column, in real
+ xChild = xChild.query( xForm );
+ xForm = xForm.query( xChild->getParent() );
+ }
+
+ OSL_ENSURE( xForm.is(), "lcl_getDataSourceIndirectProperties: could not determine the form!" );
+ if ( !xForm.is() )
+ return aInfo;
+ ::rtl::OUString sDataSourceName;
+ xForm->getPropertyValue( FM_PROP_DATASOURCE ) >>= sDataSourceName;
+
+ Reference< XPropertySet > xDsProperties;
+ if ( sDataSourceName.getLength() )
+ xDsProperties = xDsProperties.query( OStaticDataAccessTools().getDataSource( sDataSourceName, _rContext.getLegacyServiceFactory() ) );
+ if ( xDsProperties.is() )
+ xDsProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Info" ) ) ) >>= aInfo;
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "lcl_getDataSourceIndirectProperties: caught an exception!" );
+ }
+ return aInfo;
+ }
+
+ //....................................................................
+ static const sal_Char* aCharacterAndParagraphProperties[] =
+ {
+ "CharFontName",
+ "CharFontStyleName",
+ "CharFontFamily",
+ "CharFontCharSet",
+ "CharFontPitch",
+ "CharColor",
+ "CharEscapement",
+ "CharHeight",
+ "CharUnderline",
+ "CharWeight",
+ "CharPosture",
+ "CharAutoKerning",
+ "CharBackColor",
+ "CharBackTransparent",
+ "CharCaseMap",
+ "CharCrossedOut",
+ "CharFlash",
+ "CharStrikeout",
+ "CharWordMode",
+ "CharKerning",
+ "CharLocale",
+ "CharKeepTogether",
+ "CharNoLineBreak",
+ "CharShadowed",
+ "CharFontType",
+ "CharStyleName",
+ "CharContoured",
+ "CharCombineIsOn",
+ "CharCombinePrefix",
+ "CharCombineSuffix",
+ "CharEmphasize",
+ "CharRelief",
+ "RubyText",
+ "RubyAdjust",
+ "RubyCharStyleName",
+ "RubyIsAbove",
+ "CharRotation",
+ "CharRotationIsFitToLine",
+ "CharScaleWidth",
+ "HyperLinkURL",
+ "HyperLinkTarget",
+ "HyperLinkName",
+ "VisitedCharStyleName",
+ "UnvisitedCharStyleName",
+ "CharEscapementHeight",
+ "CharNoHyphenation",
+ "CharUnderlineColor",
+ "CharUnderlineHasColor",
+ "CharStyleNames",
+ "CharHeightAsian",
+ "CharWeightAsian",
+ "CharFontNameAsian",
+ "CharFontStyleNameAsian",
+ "CharFontFamilyAsian",
+ "CharFontCharSetAsian",
+ "CharFontPitchAsian",
+ "CharPostureAsian",
+ "CharLocaleAsian",
+ "ParaIsCharacterDistance",
+ "ParaIsForbiddenRules",
+ "ParaIsHangingPunctuation",
+ "CharHeightComplex",
+ "CharWeightComplex",
+ "CharFontNameComplex",
+ "CharFontStyleNameComplex",
+ "CharFontFamilyComplex",
+ "CharFontCharSetComplex",
+ "CharFontPitchComplex",
+ "CharPostureComplex",
+ "CharLocaleComplex",
+ "ParaAdjust",
+ "ParaLineSpacing",
+ "ParaBackColor",
+ "ParaBackTransparent",
+ "ParaBackGraphicURL",
+ "ParaBackGraphicFilter",
+ "ParaBackGraphicLocation",
+ "ParaLastLineAdjust",
+ "ParaExpandSingleWord",
+ "ParaLeftMargin",
+ "ParaRightMargin",
+ "ParaTopMargin",
+ "ParaBottomMargin",
+ "ParaLineNumberCount",
+ "ParaLineNumberStartValue",
+ "PageDescName",
+ "PageNumberOffset",
+ "ParaRegisterModeActive",
+ "ParaTabStops",
+ "ParaStyleName",
+ "DropCapFormat",
+ "DropCapWholeWord",
+ "ParaKeepTogether",
+ "Setting",
+ "ParaSplit",
+ "Setting",
+ "NumberingLevel",
+ "NumberingRules",
+ "NumberingStartValue",
+ "ParaIsNumberingRestart",
+ "NumberingStyleName",
+ "ParaOrphans",
+ "ParaWidows",
+ "ParaShadowFormat",
+ "LeftBorder",
+ "RightBorder",
+ "TopBorder",
+ "BottomBorder",
+ "BorderDistance",
+ "LeftBorderDistance",
+ "RightBorderDistance",
+ "TopBorderDistance",
+ "BottomBorderDistance",
+ "BreakType",
+ "DropCapCharStyleName",
+ "ParaFirstLineIndent",
+ "ParaIsAutoFirstLineIndent",
+ "ParaIsHyphenation",
+ "ParaHyphenationMaxHyphens",
+ "ParaHyphenationMaxLeadingChars",
+ "ParaHyphenationMaxTrailingChars",
+ "ParaVertAlignment",
+ "ParaUserDefinedAttributes",
+ "NumberingIsNumber",
+ "ParaIsConnectBorder",
+ NULL
+ };
+
+ //....................................................................
+ static void lcl_initializeCharacterAttributes( const Reference< XPropertySet >& _rxModel )
+ {
+ try
+ {
+ Reference< XPropertySet > xStyle( ControlLayouter::getDefaultDocumentTextStyle( _rxModel ), UNO_SET_THROW );
+
+ // transfer all properties which are described by the style
+ Reference< XPropertySetInfo > xSourcePropInfo( xStyle->getPropertySetInfo(), UNO_SET_THROW );
+ Reference< XPropertySetInfo > xDestPropInfo( _rxModel->getPropertySetInfo(), UNO_SET_THROW );
+
+ ::rtl::OUString sPropertyName;
+ const sal_Char** pCharacterProperty = aCharacterAndParagraphProperties;
+ while ( *pCharacterProperty )
+ {
+ sPropertyName = ::rtl::OUString::createFromAscii( *pCharacterProperty );
+
+ if ( xSourcePropInfo->hasPropertyByName( sPropertyName ) && xDestPropInfo->hasPropertyByName( sPropertyName ) )
+ _rxModel->setPropertyValue( sPropertyName, xStyle->getPropertyValue( sPropertyName ) );
+
+ ++pCharacterProperty;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel,
+ const Rectangle& _rControlBoundRect )
+ {
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+
+ OSL_ENSURE( _rxControlModel.is(), "FormControlFactory::initializeControlModel: invalid model!" );
+ if ( !_rxControlModel.is() )
+ return nClassId;
+
+ try
+ {
+ ControlLayouter::initializeControlLayout( _rxControlModel, _eDocType );
+
+ _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId;
+ Reference< XPropertySetInfo > xPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
+ switch ( nClassId )
+ {
+ case FormComponentType::SCROLLBAR:
+ _rxControlModel->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LiveScroll" ) ), makeAny( (sal_Bool)sal_True ) );
+ // NO break!
+ case FormComponentType::SPINBUTTON:
+ {
+ sal_Int32 eOrientation = ScrollBarOrientation::HORIZONTAL;
+ if ( !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() < _rControlBoundRect.GetHeight() ) )
+ eOrientation = ScrollBarOrientation::VERTICAL;
+ _rxControlModel->setPropertyValue( FM_PROP_ORIENTATION, makeAny( eOrientation ) );
+ }
+ break;
+
+ case FormComponentType::LISTBOX:
+ case FormComponentType::COMBOBOX:
+ {
+ sal_Bool bDropDown = !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() >= 3 * _rControlBoundRect.GetHeight() );
+ if ( xPSI->hasPropertyByName( FM_PROP_DROPDOWN ) )
+ _rxControlModel->setPropertyValue( FM_PROP_DROPDOWN, makeAny( (sal_Bool)bDropDown ) );
+ _rxControlModel->setPropertyValue( FM_PROP_LINECOUNT, makeAny( sal_Int16( 20 ) ) );
+ }
+ break;
+
+ case FormComponentType::TEXTFIELD:
+ {
+ initializeTextFieldLineEnds( _rxControlModel );
+ lcl_initializeCharacterAttributes( _rxControlModel );
+
+ if ( !_rControlBoundRect.IsEmpty()
+ && !( _rControlBoundRect.GetWidth() > 4 * _rControlBoundRect.GetHeight() )
+ )
+ {
+ if ( xPSI->hasPropertyByName( FM_PROP_MULTILINE ) )
+ _rxControlModel->setPropertyValue( FM_PROP_MULTILINE, makeAny( (sal_Bool)sal_True ) );
+ }
+ }
+ break;
+
+ case FormComponentType::RADIOBUTTON:
+ case FormComponentType::CHECKBOX:
+ case FormComponentType::FIXEDTEXT:
+ {
+ ::rtl::OUString sVertAlignPropertyName( RTL_CONSTASCII_USTRINGPARAM( "VerticalAlign" ) );
+ if ( xPSI->hasPropertyByName( sVertAlignPropertyName ) )
+ _rxControlModel->setPropertyValue( sVertAlignPropertyName, makeAny( VerticalAlignment_MIDDLE ) );
+ }
+ break;
+
+ case FormComponentType::IMAGEBUTTON:
+ case FormComponentType::IMAGECONTROL:
+ {
+ const ::rtl::OUString sScaleModeProperty( RTL_CONSTASCII_USTRINGPARAM( "ScaleMode" ) );
+ if ( xPSI->hasPropertyByName( sScaleModeProperty ) )
+ _rxControlModel->setPropertyValue( sScaleModeProperty, makeAny( ImageScaleMode::Isotropic ) );
+ }
+ break;
+ }
+
+ // initial default label for the control
+ if ( xPSI->hasPropertyByName( FM_PROP_LABEL ) )
+ {
+ ::rtl::OUString sExistingLabel;
+ OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_LABEL ) >>= sExistingLabel );
+ if ( !sExistingLabel.getLength() )
+ {
+ ::rtl::OUString sInitialLabel;
+ OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_NAME ) >>= sInitialLabel );
+
+ sal_uInt16 nTitleResId = 0;
+ switch ( nClassId )
+ {
+ case FormComponentType::COMMANDBUTTON: nTitleResId = RID_STR_PROPTITLE_PUSHBUTTON; break;
+ case FormComponentType::RADIOBUTTON: nTitleResId = RID_STR_PROPTITLE_RADIOBUTTON; break;
+ case FormComponentType::CHECKBOX: nTitleResId = RID_STR_PROPTITLE_CHECKBOX; break;
+ case FormComponentType::GROUPBOX: nTitleResId = RID_STR_PROPTITLE_GROUPBOX; break;
+ case FormComponentType::FIXEDTEXT: nTitleResId = RID_STR_PROPTITLE_FIXEDTEXT; break;
+ }
+
+ if ( nTitleResId )
+ sInitialLabel = String( SVX_RES( nTitleResId ) );
+
+ _rxControlModel->setPropertyValue(
+ FM_PROP_LABEL,
+ makeAny( lcl_getUniqueLabel_nothrow( _rxControlModel, sInitialLabel ) )
+ );
+ }
+ }
+
+ // strict format = yes is the default (i93467)
+ if ( xPSI->hasPropertyByName( FM_PROP_STRICTFORMAT ) )
+ {
+ _rxControlModel->setPropertyValue( FM_PROP_STRICTFORMAT, makeAny( sal_Bool( sal_True ) ) );
+ }
+
+ // mouse wheel: don't use it for scrolling by default (i110036)
+ if ( xPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) )
+ {
+ _rxControlModel->setPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR, makeAny( MouseWheelBehavior::SCROLL_DISABLED ) );
+ }
+
+ if ( xPSI->hasPropertyByName( FM_PROP_WRITING_MODE ) )
+ _rxControlModel->setPropertyValue( FM_PROP_WRITING_MODE, makeAny( WritingMode2::CONTEXT ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return nClassId;
+ }
+
+ //------------------------------------------------------------------------------
+ void FormControlFactory::initializeTextFieldLineEnds( const Reference< XPropertySet >& _rxModel )
+ {
+ OSL_PRECOND( _rxModel.is(), "initializeTextFieldLineEnds: invalid model!" );
+ if ( !_rxModel.is() )
+ return;
+
+ try
+ {
+ Reference< XPropertySetInfo > xInfo = _rxModel->getPropertySetInfo();
+ if ( !xInfo.is() || !xInfo->hasPropertyByName( FM_PROP_LINEENDFORMAT ) )
+ return;
+
+ // let's see if the data source which the form belongs to (if any)
+ // has a setting for the preferred line end format
+ sal_Bool bDosLineEnds = sal_False;
+ Sequence< PropertyValue > aInfo = lcl_getDataSourceIndirectProperties( _rxModel, m_pData->m_aContext );
+ const PropertyValue* pInfo = aInfo.getConstArray();
+ const PropertyValue* pInfoEnd = pInfo + aInfo.getLength();
+ for ( ; pInfo != pInfoEnd; ++pInfo )
+ {
+ if ( pInfo->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PreferDosLikeLineEnds" ) ) )
+ {
+ pInfo->Value >>= bDosLineEnds;
+ break;
+ }
+ }
+
+ sal_Int16 nLineEndFormat = bDosLineEnds ? LineEndFormat::CARRIAGE_RETURN_LINE_FEED : LineEndFormat::LINE_FEED;
+ _rxModel->setPropertyValue( FM_PROP_LINEENDFORMAT, makeAny( nLineEndFormat ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ void FormControlFactory::initializeFieldDependentProperties( const Reference< XPropertySet >& _rxDatabaseField,
+ const Reference< XPropertySet >& _rxControlModel, const Reference< XNumberFormats >& _rxNumberFormats )
+ {
+ OSL_PRECOND( _rxDatabaseField.is() && _rxControlModel.is(),
+ "FormControlFactory::initializeFieldDependentProperties: illegal params!" );
+ if ( !_rxDatabaseField.is() || !_rxControlModel.is() )
+ return;
+
+ try
+ {
+ ////////////////////////////////////////////////////////////////////////
+ // if the field has a numeric format, and the model has a "Scale" property, sync it
+ Reference< XPropertySetInfo > xFieldPSI( _rxDatabaseField->getPropertySetInfo(), UNO_SET_THROW );
+ Reference< XPropertySetInfo > xModelPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
+
+ if ( xModelPSI->hasPropertyByName( FM_PROP_DECIMAL_ACCURACY ) )
+ {
+ sal_Int32 nFormatKey = 0;
+ if ( xFieldPSI->hasPropertyByName( FM_PROP_FORMATKEY ) )
+ {
+ _rxDatabaseField->getPropertyValue( FM_PROP_FORMATKEY ) >>= nFormatKey;
+ }
+ else
+ {
+ nFormatKey = OStaticDataAccessTools().getDefaultNumberFormat(
+ _rxDatabaseField,
+ Reference< XNumberFormatTypes >( _rxNumberFormats, UNO_QUERY ),
+ SvtSysLocale().GetLocaleData().getLocale()
+ );
+ }
+
+ Any aScaleVal( ::comphelper::getNumberFormatDecimals( _rxNumberFormats, nFormatKey ) );
+ _rxControlModel->setPropertyValue( FM_PROP_DECIMAL_ACCURACY, aScaleVal );
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // minimum and maximum of the control according to the type of the database field
+ sal_Int32 nDataType = DataType::OTHER;
+ OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType );
+
+ if ( xModelPSI->hasPropertyByName( FM_PROP_VALUEMIN )
+ && xModelPSI->hasPropertyByName( FM_PROP_VALUEMAX )
+ )
+ {
+ sal_Int32 nMinValue = -1000000000, nMaxValue = 1000000000;
+ switch ( nDataType )
+ {
+ case DataType::TINYINT : nMinValue = 0; nMaxValue = 255; break;
+ case DataType::SMALLINT : nMinValue = -32768; nMaxValue = 32767; break;
+ case DataType::INTEGER : nMinValue = 0x80000000; nMaxValue = 0x7FFFFFFF; break;
+ // double and singles are ignored
+ }
+
+ Any aValue;
+
+ // both the minimum and the maximum value properties can be either Long or Double
+ Property aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMIN );
+ if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE )
+ aValue <<= (double)nMinValue;
+ else if ( aProperty.Type.getTypeClass() == TypeClass_LONG )
+ aValue <<= (sal_Int32)nMinValue;
+ else
+ {
+ DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MinValue)!" );
+ }
+ _rxControlModel->setPropertyValue( FM_PROP_VALUEMIN, aValue );
+
+ // both the minimum and the maximum value properties can be either Long or Double
+ aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMAX );
+ if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE )
+ aValue <<= (double)nMaxValue;
+ else if ( aProperty.Type.getTypeClass() == TypeClass_LONG )
+ aValue <<= (sal_Int32)nMaxValue;
+ else
+ {
+ DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MaxValue)!" );
+ }
+ _rxControlModel->setPropertyValue( FM_PROP_VALUEMAX, aValue );
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // a check box can be tristate if and only if the column it is bound to is nullable
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+ OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
+ if ( nClassId == FormComponentType::CHECKBOX )
+ {
+ sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
+ OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_ISNULLABLE ) >>= nNullable );
+ _rxControlModel->setPropertyValue( FM_PROP_TRISTATE, makeAny( sal_Bool( ColumnValue::NO_NULLS != nNullable ) ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ ::rtl::OUString FormControlFactory::getDefaultName( sal_Int16 _nClassId, const Reference< XServiceInfo >& _rxObject )
+ {
+ sal_uInt16 nResId(0);
+
+ switch ( _nClassId )
+ {
+ case FormComponentType::COMMANDBUTTON: nResId = RID_STR_PROPTITLE_PUSHBUTTON; break;
+ case FormComponentType::RADIOBUTTON: nResId = RID_STR_PROPTITLE_RADIOBUTTON; break;
+ case FormComponentType::CHECKBOX: nResId = RID_STR_PROPTITLE_CHECKBOX; break;
+ case FormComponentType::LISTBOX: nResId = RID_STR_PROPTITLE_LISTBOX; break;
+ case FormComponentType::COMBOBOX: nResId = RID_STR_PROPTITLE_COMBOBOX; break;
+ case FormComponentType::GROUPBOX: nResId = RID_STR_PROPTITLE_GROUPBOX; break;
+ case FormComponentType::IMAGEBUTTON: nResId = RID_STR_PROPTITLE_IMAGEBUTTON; break;
+ case FormComponentType::FIXEDTEXT: nResId = RID_STR_PROPTITLE_FIXEDTEXT; break;
+ case FormComponentType::GRIDCONTROL: nResId = RID_STR_PROPTITLE_DBGRID; break;
+ case FormComponentType::FILECONTROL: nResId = RID_STR_PROPTITLE_FILECONTROL; break;
+ case FormComponentType::DATEFIELD: nResId = RID_STR_PROPTITLE_DATEFIELD; break;
+ case FormComponentType::TIMEFIELD: nResId = RID_STR_PROPTITLE_TIMEFIELD; break;
+ case FormComponentType::NUMERICFIELD: nResId = RID_STR_PROPTITLE_NUMERICFIELD; break;
+ case FormComponentType::CURRENCYFIELD: nResId = RID_STR_PROPTITLE_CURRENCYFIELD; break;
+ case FormComponentType::PATTERNFIELD: nResId = RID_STR_PROPTITLE_PATTERNFIELD; break;
+ case FormComponentType::IMAGECONTROL: nResId = RID_STR_PROPTITLE_IMAGECONTROL; break;
+ case FormComponentType::HIDDENCONTROL: nResId = RID_STR_PROPTITLE_HIDDEN; break;
+ case FormComponentType::SCROLLBAR: nResId = RID_STR_PROPTITLE_SCROLLBAR; break;
+ case FormComponentType::SPINBUTTON: nResId = RID_STR_PROPTITLE_SPINBUTTON; break;
+ case FormComponentType::NAVIGATIONBAR: nResId = RID_STR_PROPTITLE_NAVBAR; break;
+
+ case FormComponentType::TEXTFIELD:
+ nResId = RID_STR_PROPTITLE_EDIT;
+ if ( _rxObject.is() && _rxObject->supportsService( FM_SUN_COMPONENT_FORMATTEDFIELD ) )
+ nResId = RID_STR_PROPTITLE_FORMATTED;
+ break;
+
+ default:
+ nResId = RID_STR_CONTROL; break;
+ }
+
+ return String( SVX_RES( nResId ) );
+ }
+
+ //------------------------------------------------------------------------------
+ ::rtl::OUString FormControlFactory::getDefaultUniqueName_ByComponentType( const Reference< XNameAccess >& _rxContainer,
+ const Reference< XPropertySet >& _rxObject )
+ {
+ sal_Int16 nClassId = FormComponentType::CONTROL;
+ OSL_VERIFY( _rxObject->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
+ ::rtl::OUString sBaseName = getDefaultName( nClassId, Reference< XServiceInfo >( _rxObject, UNO_QUERY ) );
+
+ return getUniqueName( _rxContainer, sBaseName );
+ }
+
+ //------------------------------------------------------------------------------
+ ::rtl::OUString FormControlFactory::getUniqueName( const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rBaseName )
+ {
+ sal_Int32 n = 0;
+ ::rtl::OUString sName;
+ do
+ {
+ ::rtl::OUStringBuffer aBuf( _rBaseName );
+ aBuf.appendAscii( " " );
+ aBuf.append( ++n );
+ sName = aBuf.makeStringAndClear();
+ }
+ while ( _rxContainer->hasByName( sName ) );
+
+ return sName;
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formcontroller.cxx b/svx/source/form/formcontroller.cxx
new file mode 100644
index 000000000000..552744a30e02
--- /dev/null
+++ b/svx/source/form/formcontroller.cxx
@@ -0,0 +1,4320 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmcontrolbordermanager.hxx"
+#include "fmcontrollayout.hxx"
+#include "formcontroller.hxx"
+#include "formfeaturedispatcher.hxx"
+#include "fmdocumentclassification.hxx"
+#include "formcontrolling.hxx"
+#include "fmprop.hrc"
+#include "svx/dialmgr.hxx"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "svx/fmtools.hxx"
+#include "fmurl.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/awt/FocusChangeReason.hpp>
+#include <com/sun/star/awt/XCheckBox.hpp>
+#include <com/sun/star/awt/XComboBox.hpp>
+#include <com/sun/star/awt/XListBox.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XIdentifierReplace.hpp>
+#include <com/sun/star/form/TabulatorCycle.hpp>
+#include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
+#include <com/sun/star/form/XBoundComponent.hpp>
+#include <com/sun/star/form/XBoundControl.hpp>
+#include <com/sun/star/form/XGridControl.hpp>
+#include <com/sun/star/form/XLoadable.hpp>
+#include <com/sun/star/form/XReset.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/sdb/ParametersRequest.hpp>
+#include <com/sun/star/sdb/RowChangeAction.hpp>
+#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/form/runtime/FormOperations.hpp>
+#include <com/sun/star/form/runtime/FormFeature.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdb/XColumn.hpp>
+/** === end UNO includes === **/
+
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/interaction.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/propagg.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <toolkit/controls/unocontrol.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/shl.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/logfile.hxx>
+
+#include <algorithm>
+#include <functional>
+
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+using namespace ::connectivity;
+using namespace ::connectivity::simple;
+
+//------------------------------------------------------------------
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
+ FormController_NewInstance_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & _rxORB )
+{
+ return *( new ::svxform::FormController( _rxORB ) );
+}
+
+namespace svxform
+{
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::sdb::XColumn;
+ using ::com::sun::star::awt::XControl;
+ using ::com::sun::star::awt::XTabController;
+ using ::com::sun::star::awt::XToolkit;
+ using ::com::sun::star::awt::XWindowPeer;
+ using ::com::sun::star::form::XGrid;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::container::XIndexAccess;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::lang::IndexOutOfBoundsException;
+ using ::com::sun::star::sdb::XInteractionSupplyParameters;
+ using ::com::sun::star::awt::XTextComponent;
+ using ::com::sun::star::awt::XTextListener;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::frame::XDispatch;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::uno::XAggregation;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdbc::XRowSet;
+ using ::com::sun::star::sdbc::XDatabaseMetaData;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::util::XNumberFormatter;
+ using ::com::sun::star::sdbcx::XColumnsSupplier;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::container::XEnumeration;
+ using ::com::sun::star::form::XFormComponent;
+ using ::com::sun::star::form::runtime::XFormOperations;
+ using ::com::sun::star::form::runtime::FilterEvent;
+ using ::com::sun::star::form::runtime::XFilterControllerListener;
+ using ::com::sun::star::awt::XControlContainer;
+ using ::com::sun::star::container::XIdentifierReplace;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::form::XFormControllerListener;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::sdbc::XResultSet;
+ using ::com::sun::star::awt::XControlModel;
+ using ::com::sun::star::awt::XTabControllerModel;
+ using ::com::sun::star::beans::PropertyChangeEvent;
+ using ::com::sun::star::form::validation::XValidatableFormComponent;
+ using ::com::sun::star::form::XLoadable;
+ using ::com::sun::star::script::XEventAttacherManager;
+ using ::com::sun::star::form::XBoundControl;
+ using ::com::sun::star::beans::XPropertyChangeListener;
+ using ::com::sun::star::awt::TextEvent;
+ using ::com::sun::star::form::XBoundComponent;
+ using ::com::sun::star::awt::XCheckBox;
+ using ::com::sun::star::awt::XComboBox;
+ using ::com::sun::star::awt::XListBox;
+ using ::com::sun::star::awt::ItemEvent;
+ using ::com::sun::star::util::XModifyListener;
+ using ::com::sun::star::form::XReset;
+ using ::com::sun::star::frame::XDispatchProviderInterception;
+ using ::com::sun::star::form::XGridControl;
+ using ::com::sun::star::awt::XVclWindowPeer;
+ using ::com::sun::star::form::validation::XValidator;
+ using ::com::sun::star::awt::FocusEvent;
+ using ::com::sun::star::sdb::SQLContext;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::form::TabulatorCycle_RECORDS;
+ using ::com::sun::star::container::ContainerEvent;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::lang::Locale;
+ using ::com::sun::star::beans::NamedValue;
+ using ::com::sun::star::lang::NoSupportException;
+ using ::com::sun::star::sdb::RowChangeEvent;
+ using ::com::sun::star::frame::XStatusListener;
+ using ::com::sun::star::frame::XDispatchProviderInterceptor;
+ using ::com::sun::star::sdb::SQLErrorEvent;
+ using ::com::sun::star::form::DatabaseParameterEvent;
+ using ::com::sun::star::sdb::ParametersRequest;
+ using ::com::sun::star::task::XInteractionRequest;
+ using ::com::sun::star::util::URL;
+ using ::com::sun::star::frame::FeatureStateEvent;
+ using ::com::sun::star::form::runtime::XFormControllerContext;
+ using ::com::sun::star::task::XInteractionHandler;
+ using ::com::sun::star::form::runtime::FormOperations;
+ using ::com::sun::star::container::XContainer;
+ using ::com::sun::star::sdbc::SQLWarning;
+ /** === end UNO using === **/
+ namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+ namespace FocusChangeReason = ::com::sun::star::awt::FocusChangeReason;
+ namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
+ namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
+
+//==============================================================================
+// ColumnInfo
+//==============================================================================
+struct ColumnInfo
+{
+ // information about the column itself
+ Reference< XColumn > xColumn;
+ sal_Int32 nNullable;
+ sal_Bool bAutoIncrement;
+ sal_Bool bReadOnly;
+ ::rtl::OUString sName;
+
+ // information about the control(s) bound to this column
+
+ /// the first control which is bound to the given column, and which requires input
+ Reference< XControl > xFirstControlWithInputRequired;
+ /** the first grid control which contains a column which is bound to the given database column, and requires
+ input
+ */
+ Reference< XGrid > xFirstGridWithInputRequiredColumn;
+ /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
+ of the grid column which is actually bound
+ */
+ sal_Int32 nRequiredGridColumn;
+
+ ColumnInfo()
+ :xColumn()
+ ,nNullable( ColumnValue::NULLABLE_UNKNOWN )
+ ,bAutoIncrement( sal_False )
+ ,bReadOnly( sal_False )
+ ,sName()
+ ,xFirstControlWithInputRequired()
+ ,xFirstGridWithInputRequiredColumn()
+ ,nRequiredGridColumn( -1 )
+ {
+ }
+};
+
+//==============================================================================
+//= ColumnInfoCache
+//==============================================================================
+class ColumnInfoCache
+{
+public:
+ ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier );
+
+ size_t getColumnCount() const { return m_aColumns.size(); }
+ const ColumnInfo& getColumnInfo( size_t _pos );
+
+ bool controlsInitialized() const { return m_bControlsInitialized; }
+ void initializeControls( const Sequence< Reference< XControl > >& _rControls );
+ void deinitializeControls();
+
+private:
+ typedef ::std::vector< ColumnInfo > ColumnInfos;
+ ColumnInfos m_aColumns;
+ bool m_bControlsInitialized;
+};
+
+//------------------------------------------------------------------------------
+ColumnInfoCache::ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier )
+ :m_aColumns()
+ ,m_bControlsInitialized( false )
+{
+ try
+ {
+ m_aColumns.clear();
+
+ Reference< XColumnsSupplier > xSupplyCols( _rxColSupplier, UNO_SET_THROW );
+ Reference< XIndexAccess > xColumns( xSupplyCols->getColumns(), UNO_QUERY_THROW );
+ sal_Int32 nColumnCount = xColumns->getCount();
+ m_aColumns.reserve( nColumnCount );
+
+ Reference< XPropertySet > xColumnProps;
+ for ( sal_Int32 i = 0; i < nColumnCount; ++i )
+ {
+ ColumnInfo aColInfo;
+ aColInfo.xColumn.set( xColumns->getByIndex(i), UNO_QUERY_THROW );
+
+ xColumnProps.set( aColInfo.xColumn, UNO_QUERY_THROW );
+ OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISNULLABLE ) >>= aColInfo.nNullable );
+ OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_AUTOINCREMENT ) >>= aColInfo.bAutoIncrement );
+ OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_NAME ) >>= aColInfo.sName );
+ OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISREADONLY ) >>= aColInfo.bReadOnly );
+
+ m_aColumns.push_back( aColInfo );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ bool lcl_isBoundTo( const Reference< XPropertySet >& _rxControlModel, const Reference< XInterface >& _rxNormDBField )
+ {
+ Reference< XInterface > xNormBoundField( _rxControlModel->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY );
+ return ( xNormBoundField.get() == _rxNormDBField.get() );
+ }
+
+ bool lcl_isInputRequired( const Reference< XPropertySet >& _rxControlModel )
+ {
+ sal_Bool bInputRequired = sal_True;
+ OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_INPUT_REQUIRED ) >>= bInputRequired );
+ return ( bInputRequired != sal_False );
+ }
+
+ void lcl_resetColumnControlInfo( ColumnInfo& _rColInfo )
+ {
+ _rColInfo.xFirstControlWithInputRequired.clear();
+ _rColInfo.xFirstGridWithInputRequiredColumn.clear();
+ _rColInfo.nRequiredGridColumn = -1;
+ }
+}
+
+//------------------------------------------------------------------------------
+void ColumnInfoCache::deinitializeControls()
+{
+ for ( ColumnInfos::iterator col = m_aColumns.begin();
+ col != m_aColumns.end();
+ ++col
+ )
+ {
+ lcl_resetColumnControlInfo( *col );
+ }
+}
+
+//------------------------------------------------------------------------------
+void ColumnInfoCache::initializeControls( const Sequence< Reference< XControl > >& _rControls )
+{
+ try
+ {
+ // for every of our known columns, find the controls which are bound to this column
+ for ( ColumnInfos::iterator col = m_aColumns.begin();
+ col != m_aColumns.end();
+ ++col
+ )
+ {
+ OSL_ENSURE( !col->xFirstControlWithInputRequired.is() && !col->xFirstGridWithInputRequiredColumn.is()
+ && ( col->nRequiredGridColumn == -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
+
+ lcl_resetColumnControlInfo( *col );
+
+ Reference< XInterface > xNormColumn( col->xColumn, UNO_QUERY_THROW );
+
+ const Reference< XControl >* pControl( _rControls.getConstArray() );
+ const Reference< XControl >* pControlEnd( pControl + _rControls.getLength() );
+ for ( ; pControl != pControlEnd; ++pControl )
+ {
+ if ( !pControl->is() )
+ continue;
+
+ Reference< XPropertySet > xModel( (*pControl)->getModel(), UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
+
+ // special handling for grid controls
+ Reference< XGrid > xGrid( *pControl, UNO_QUERY );
+ if ( xGrid.is() )
+ {
+ Reference< XIndexAccess > xGridColAccess( xModel, UNO_QUERY_THROW );
+ sal_Int32 gridColCount = xGridColAccess->getCount();
+ sal_Int32 gridCol = 0;
+ for ( gridCol = 0; gridCol < gridColCount; ++gridCol )
+ {
+ Reference< XPropertySet > xGridColumnModel( xGridColAccess->getByIndex( gridCol ), UNO_QUERY_THROW );
+
+ if ( !lcl_isBoundTo( xGridColumnModel, xNormColumn )
+ || !lcl_isInputRequired( xGridColumnModel )
+ )
+ continue; // with next grid column
+
+ break;
+ }
+
+ if ( gridCol < gridColCount )
+ {
+ // found a grid column which is bound to the given
+ col->xFirstGridWithInputRequiredColumn = xGrid;
+ col->nRequiredGridColumn = gridCol;
+ break;
+ }
+
+ continue; // with next control
+ }
+
+ if ( !xModelPSI->hasPropertyByName( FM_PROP_BOUNDFIELD )
+ || !lcl_isBoundTo( xModel, xNormColumn )
+ || !lcl_isInputRequired( xModel )
+ )
+ continue; // with next control
+
+ break;
+ }
+
+ if ( pControl == pControlEnd )
+ // did not find a control which is bound to this particular column, and for which the input is required
+ continue; // with next DB column
+
+ col->xFirstControlWithInputRequired = *pControl;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ m_bControlsInitialized = true;
+}
+
+//------------------------------------------------------------------------------
+const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos )
+{
+ if ( _pos >= m_aColumns.size() )
+ throw IndexOutOfBoundsException();
+
+ return m_aColumns[ _pos ];
+}
+
+//==================================================================
+// OParameterContinuation
+//==================================================================
+class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
+{
+ Sequence< PropertyValue > m_aValues;
+
+public:
+ OParameterContinuation() { }
+
+ Sequence< PropertyValue > getValues() const { return m_aValues; }
+
+// XInteractionSupplyParameters
+ virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException);
+};
+
+//------------------------------------------------------------------
+void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw(RuntimeException)
+{
+ m_aValues = _rValues;
+}
+
+//==================================================================
+// FmXAutoControl
+//==================================================================
+struct FmFieldInfo
+{
+ rtl::OUString aFieldName;
+ Reference< XPropertySet > xField;
+ Reference< XTextComponent > xText;
+
+ FmFieldInfo(const Reference< XPropertySet >& _xField, const Reference< XTextComponent >& _xText)
+ :xField(_xField)
+ ,xText(_xText)
+ {xField->getPropertyValue(FM_PROP_NAME) >>= aFieldName;}
+};
+
+//==================================================================
+// FmXAutoControl
+//==================================================================
+class FmXAutoControl: public UnoControl
+
+{
+ friend Reference< XInterface > SAL_CALL FmXAutoControl_NewInstance_Impl();
+
+public:
+ FmXAutoControl(){}
+
+ virtual ::rtl::OUString GetComponentServiceName() {return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Edit"));}
+ virtual void SAL_CALL createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw( RuntimeException );
+
+protected:
+ virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal );
+};
+
+//------------------------------------------------------------------------------
+void FmXAutoControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw( RuntimeException )
+{
+ UnoControl::createPeer( rxToolkit, rParentPeer );
+
+ Reference< XTextComponent > xText(getPeer() , UNO_QUERY);
+ if (xText.is())
+ {
+ xText->setText(::rtl::OUString(String(SVX_RES(RID_STR_AUTOFIELD))));
+ xText->setEditable(sal_False);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmXAutoControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
+{
+ // these properties are ignored
+ if (rPropName == FM_PROP_TEXT)
+ return;
+
+ UnoControl::ImplSetPeerProperty( rPropName, rVal );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK( FormController, OnActivateTabOrder, void*, /*EMPTYTAG*/ )
+{
+ activateTabOrder();
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+struct UpdateAllListeners : public ::std::unary_function< Reference< XDispatch >, bool >
+{
+ bool operator()( const Reference< XDispatch >& _rxDispatcher ) const
+ {
+ static_cast< ::svx::OSingleFeatureDispatcher* >( _rxDispatcher.get() )->updateAllListeners();
+ // the return is a dummy only so we can use this struct in a std::compose1 call
+ return true;
+ }
+};
+//..............................................................................
+IMPL_LINK( FormController, OnInvalidateFeatures, void*, /*_pNotInterestedInThisParam*/ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ for ( ::std::set< sal_Int16 >::const_iterator aLoop = m_aInvalidFeatures.begin();
+ aLoop != m_aInvalidFeatures.end();
+ ++aLoop
+ )
+ {
+ DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( *aLoop );
+ if ( aDispatcherPos != m_aFeatureDispatchers.end() )
+ {
+ // TODO: for the real and actual listener notifications, we should release
+ // our mutex
+ UpdateAllListeners( )( aDispatcherPos->second );
+ }
+ }
+ return 1;
+}
+
+/*************************************************************************/
+
+DBG_NAME( FormController )
+//------------------------------------------------------------------
+FormController::FormController(const Reference< XMultiServiceFactory > & _rxORB )
+ :FormController_BASE( m_aMutex )
+ ,OPropertySetHelper( FormController_BASE::rBHelper )
+ ,OSQLParserClient( _rxORB )
+ ,m_aContext( _rxORB )
+ ,m_aActivateListeners(m_aMutex)
+ ,m_aModifyListeners(m_aMutex)
+ ,m_aErrorListeners(m_aMutex)
+ ,m_aDeleteListeners(m_aMutex)
+ ,m_aRowSetApproveListeners(m_aMutex)
+ ,m_aParameterListeners(m_aMutex)
+ ,m_aFilterListeners(m_aMutex)
+ ,m_pControlBorderManager( new ::svxform::ControlBorderManager )
+ ,m_xFormOperations()
+ ,m_aMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) )
+ ,m_aLoadEvent( LINK( this, FormController, OnLoad ) )
+ ,m_aToggleEvent( LINK( this, FormController, OnToggleAutoFields ) )
+ ,m_aActivationEvent( LINK( this, FormController, OnActivated ) )
+ ,m_aDeactivationEvent( LINK( this, FormController, OnDeactivated ) )
+ ,m_nCurrentFilterPosition(-1)
+ ,m_bCurrentRecordModified(sal_False)
+ ,m_bCurrentRecordNew(sal_False)
+ ,m_bLocked(sal_False)
+ ,m_bDBConnection(sal_False)
+ ,m_bCycle(sal_False)
+ ,m_bCanInsert(sal_False)
+ ,m_bCanUpdate(sal_False)
+ ,m_bCommitLock(sal_False)
+ ,m_bModified(sal_False)
+ ,m_bControlsSorted(sal_False)
+ ,m_bFiltering(sal_False)
+ ,m_bAttachEvents(sal_True)
+ ,m_bDetachEvents(sal_True)
+ ,m_bAttemptedHandlerCreation( false )
+{
+ DBG_CTOR( FormController, NULL );
+
+ ::comphelper::increment(m_refCount);
+ {
+ {
+ m_xAggregate = Reference< XAggregation >(
+ m_aContext.createComponent( "com.sun.star.awt.TabController" ),
+ UNO_QUERY
+ );
+ DBG_ASSERT( m_xAggregate.is(), "FormController::FormController : could not create my aggregate !" );
+ m_xTabController = Reference< XTabController >( m_xAggregate, UNO_QUERY );
+ }
+
+ if ( m_xAggregate.is() )
+ m_xAggregate->setDelegator( *this );
+ }
+ ::comphelper::decrement(m_refCount);
+
+ m_aTabActivationTimer.SetTimeout( 500 );
+ m_aTabActivationTimer.SetTimeoutHdl( LINK( this, FormController, OnActivateTabOrder ) );
+
+ m_aFeatureInvalidationTimer.SetTimeout( 200 );
+ m_aFeatureInvalidationTimer.SetTimeoutHdl( LINK( this, FormController, OnInvalidateFeatures ) );
+}
+
+//------------------------------------------------------------------
+FormController::~FormController()
+{
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ m_aLoadEvent.CancelPendingCall();
+ m_aToggleEvent.CancelPendingCall();
+ m_aActivationEvent.CancelPendingCall();
+ m_aDeactivationEvent.CancelPendingCall();
+
+ if ( m_aTabActivationTimer.IsActive() )
+ m_aTabActivationTimer.Stop();
+ }
+
+ if ( m_aFeatureInvalidationTimer.IsActive() )
+ m_aFeatureInvalidationTimer.Stop();
+
+ disposeAllFeaturesAndDispatchers();
+
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->dispose();
+ m_xFormOperations.clear();
+
+ // Freigeben der Aggregation
+ if ( m_xAggregate.is() )
+ {
+ m_xAggregate->setDelegator( NULL );
+ m_xAggregate.clear();
+ }
+
+ DELETEZ( m_pControlBorderManager );
+
+ DBG_DTOR( FormController, NULL );
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL FormController::acquire() throw ()
+{
+ FormController_BASE::acquire();
+}
+
+// -----------------------------------------------------------------------------
+void SAL_CALL FormController::release() throw ()
+{
+ FormController_BASE::release();
+}
+
+//------------------------------------------------------------------
+Any SAL_CALL FormController::queryInterface( const Type& _rType ) throw(RuntimeException)
+{
+ Any aRet = FormController_BASE::queryInterface( _rType );
+ if ( !aRet.hasValue() )
+ aRet = OPropertySetHelper::queryInterface( _rType );
+ if ( !aRet.hasValue() )
+ aRet = m_xAggregate->queryAggregation( _rType );
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId() throw( RuntimeException )
+{
+ static ::cppu::OImplementationId* pId = NULL;
+ if ( !pId )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( !pId )
+ {
+ static ::cppu::OImplementationId aId;
+ pId = &aId;
+ }
+ }
+ return pId->getImplementationId();
+}
+
+//------------------------------------------------------------------------------
+Sequence< Type > SAL_CALL FormController::getTypes( ) throw(RuntimeException)
+{
+ return comphelper::concatSequences(
+ FormController_BASE::getTypes(),
+ ::cppu::OPropertySetHelper::getTypes()
+ );
+}
+
+// XServiceInfo
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::supportsService(const ::rtl::OUString& ServiceName) throw( RuntimeException )
+{
+ Sequence< ::rtl::OUString> aSNL(getSupportedServiceNames());
+ const ::rtl::OUString * pArray = aSNL.getConstArray();
+ for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
+ if( pArray[i] == ServiceName )
+ return sal_True;
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+::rtl::OUString SAL_CALL FormController::getImplementationName() throw( RuntimeException )
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.svx.FormController"));
+}
+
+//------------------------------------------------------------------------------
+Sequence< ::rtl::OUString> SAL_CALL FormController::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ // service names which are supported only, but cannot be used to created an
+ // instance at a service factory
+ Sequence< ::rtl::OUString > aNonCreatableServiceNames( 1 );
+ aNonCreatableServiceNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.FormControllerDispatcher" ) );
+
+ // services which can be used to created an instance at a service factory
+ Sequence< ::rtl::OUString > aCreatableServiceNames( getSupportedServiceNames_Static() );
+ return ::comphelper::concatSequences( aCreatableServiceNames, aNonCreatableServiceNames );
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException )
+{
+ return sal_True;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::resetted(const EventObject& rEvent) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (getCurrentControl().is() && (getCurrentControl()->getModel() == rEvent.Source))
+ m_bModified = sal_False;
+}
+
+//------------------------------------------------------------------------------
+Sequence< ::rtl::OUString> FormController::getSupportedServiceNames_Static(void)
+{
+ static Sequence< ::rtl::OUString> aServices;
+ if (!aServices.getLength())
+ {
+ aServices.realloc(2);
+ aServices.getArray()[0] = FM_FORM_CONTROLLER;
+ aServices.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.control.TabController"));
+ }
+ return aServices;
+}
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ struct ResetComponentText : public ::std::unary_function< Reference< XTextComponent >, void >
+ {
+ void operator()( const Reference< XTextComponent >& _rxText )
+ {
+ _rxText->setText( ::rtl::OUString() );
+ }
+ };
+
+ struct RemoveComponentTextListener : public ::std::unary_function< Reference< XTextComponent >, void >
+ {
+ RemoveComponentTextListener( const Reference< XTextListener >& _rxListener )
+ :m_xListener( _rxListener )
+ {
+ }
+
+ void operator()( const Reference< XTextComponent >& _rxText )
+ {
+ _rxText->removeTextListener( m_xListener );
+ }
+
+ private:
+ Reference< XTextListener > m_xListener;
+ };
+}
+
+// -----------------------------------------------------------------------------
+void FormController::impl_setTextOnAllFilter_throw()
+{
+ // reset the text for all controls
+ ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), ResetComponentText() );
+
+ if ( m_aFilterRows.empty() )
+ // nothing to do anymore
+ return;
+
+ if ( m_nCurrentFilterPosition < 0 )
+ return;
+
+ // set the text for all filters
+ OSL_ENSURE( m_aFilterRows.size() > (size_t)m_nCurrentFilterPosition,
+ "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
+
+ if ( (size_t)m_nCurrentFilterPosition < m_aFilterRows.size() )
+ {
+ FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
+ for ( FmFilterRow::const_iterator iter2 = rRow.begin();
+ iter2 != rRow.end();
+ ++iter2
+ )
+ {
+ iter2->first->setText( iter2->second );
+ }
+ }
+}
+// OPropertySetHelper
+//------------------------------------------------------------------------------
+sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/,
+ sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
+ throw( IllegalArgumentException )
+{
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
+ throw( Exception )
+{
+}
+
+//------------------------------------------------------------------------------
+void FormController::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ switch (nHandle)
+ {
+ case FM_ATTR_FILTER:
+ {
+ ::rtl::OUStringBuffer aFilter;
+ OStaticDataAccessTools aStaticTools;
+ Reference<XConnection> xConnection(aStaticTools.getRowSetConnection(Reference< XRowSet>(m_xModelAsIndex, UNO_QUERY)));
+ if (xConnection.is())
+ {
+ Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
+ Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats( xConnection, sal_True ) );
+ Reference< XNumberFormatter> xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW );
+ xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
+
+ Reference< XColumnsSupplier> xSupplyCols(m_xModelAsIndex, UNO_QUERY);
+ Reference< XNameAccess> xFields(xSupplyCols->getColumns(), UNO_QUERY);
+
+ ::rtl::OUString aQuote( xMetaData->getIdentifierQuoteString() );
+
+ // now add the filter rows
+ try
+ {
+ for ( FmFilterRows::const_iterator row = m_aFilterRows.begin(); row != m_aFilterRows.end(); ++row )
+ {
+ const FmFilterRow& rRow = *row;
+
+ if ( rRow.empty() )
+ continue;
+
+ if ( aFilter.getLength() )
+ aFilter.appendAscii( " OR " );
+
+ aFilter.appendAscii( "( " );
+ for ( FmFilterRow::const_iterator condition = rRow.begin(); condition != rRow.end(); ++condition )
+ {
+ // get the field of the controls map
+ Reference< XControl > xControl( condition->first, UNO_QUERY_THROW );
+ Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
+ Reference< XPropertySet > xField( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
+ if ( condition != rRow.begin() )
+ aFilter.appendAscii( " AND " );
+
+ ::rtl::OUString sFilterValue( condition->second );
+
+ ::rtl::OUString sErrorMsg, sCriteria;
+ ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree( sErrorMsg, sFilterValue, xFormatter, xField );
+ OSL_ENSURE( xParseNode.is(), "FormController::getFastPropertyValue: could not parse the field value predicate!" );
+ if ( xParseNode.is() )
+ {
+ // don't use a parse context here, we need it unlocalized
+ xParseNode->parseNodeToStr( sCriteria, xConnection, NULL );
+ aFilter.append( sCriteria );
+ }
+ }
+ aFilter.appendAscii( " )" );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ aFilter.setLength(0);
+ }
+ }
+ rValue <<= aFilter.makeStringAndClear();
+ }
+ break;
+
+ case FM_ATTR_FORM_OPERATIONS:
+ rValue <<= m_xFormOperations;
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XPropertySetInfo > FormController::getPropertySetInfo() throw( RuntimeException )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+//------------------------------------------------------------------------------
+#define DECL_PROP_CORE(varname, type) \
+pDesc[nPos++] = Property(FM_PROP_##varname, FM_ATTR_##varname, ::getCppuType((const type*)0),
+
+
+#define DECL_PROP1(varname, type, attrib1) \
+ DECL_PROP_CORE(varname, type) PropertyAttribute::attrib1)
+
+//------------------------------------------------------------------------------
+void FormController::fillProperties(
+ Sequence< Property >& /* [out] */ _rProps,
+ Sequence< Property >& /* [out] */ /*_rAggregateProps*/
+ ) const
+{
+ _rProps.realloc(2);
+ sal_Int32 nPos = 0;
+ Property* pDesc = _rProps.getArray();
+ DECL_PROP1(FILTER, rtl::OUString, READONLY);
+ DECL_PROP1(FORM_OPERATIONS, Reference< XFormOperations >, READONLY);
+}
+
+//------------------------------------------------------------------------------
+::cppu::IPropertyArrayHelper& FormController::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+// XFilterController
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException )
+{
+ m_aFilterListeners.addInterface( _Listener );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeFilterControllerListener( const Reference< XFilterControllerListener >& _Listener ) throw( RuntimeException )
+{
+ m_aFilterListeners.removeInterface( _Listener );
+}
+
+//------------------------------------------------------------------------------
+::sal_Int32 SAL_CALL FormController::getFilterComponents() throw( ::com::sun::star::uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ return m_aFilterComponents.size();
+}
+
+//------------------------------------------------------------------------------
+::sal_Int32 SAL_CALL FormController::getDisjunctiveTerms() throw( ::com::sun::star::uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ return m_aFilterRows.size();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::setPredicateExpression( ::sal_Int32 _Component, ::sal_Int32 _Term, const ::rtl::OUString& _PredicateExpression ) throw( RuntimeException, IndexOutOfBoundsException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) || ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
+
+ Reference< XTextComponent > xText( m_aFilterComponents[ _Component ] );
+ xText->setText( _PredicateExpression );
+
+ FmFilterRow& rFilterRow = m_aFilterRows[ _Term ];
+ if ( _PredicateExpression.getLength() )
+ rFilterRow[ xText ] = _PredicateExpression;
+ else
+ rFilterRow.erase( xText );
+}
+
+//------------------------------------------------------------------------------
+Reference< XControl > FormController::getFilterComponent( ::sal_Int32 _Component ) throw( RuntimeException, IndexOutOfBoundsException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
+
+ return Reference< XControl >( m_aFilterComponents[ _Component ], UNO_QUERY );
+}
+
+//------------------------------------------------------------------------------
+Sequence< Sequence< ::rtl::OUString > > FormController::getPredicateExpressions() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ Sequence< Sequence< ::rtl::OUString > > aExpressions( m_aFilterRows.size() );
+ sal_Int32 termIndex = 0;
+ for ( FmFilterRows::const_iterator row = m_aFilterRows.begin();
+ row != m_aFilterRows.end();
+ ++row, ++termIndex
+ )
+ {
+ const FmFilterRow& rRow( *row );
+
+ Sequence< ::rtl::OUString > aConjunction( m_aFilterComponents.size() );
+ sal_Int32 componentIndex = 0;
+ for ( FilterComponents::const_iterator comp = m_aFilterComponents.begin();
+ comp != m_aFilterComponents.end();
+ ++comp, ++componentIndex
+ )
+ {
+ FmFilterRow::const_iterator predicate = rRow.find( *comp );
+ if ( predicate != rRow.end() )
+ aConjunction[ componentIndex ] = predicate->second;
+ }
+
+ aExpressions[ termIndex ] = aConjunction;
+ }
+
+ return aExpressions;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeDisjunctiveTerm( ::sal_Int32 _Term ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ // SYNCHRONIZED -->
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if ( ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
+
+ // if the to-be-deleted row is our current row, we need to shift
+ if ( _Term == m_nCurrentFilterPosition )
+ {
+ if ( m_nCurrentFilterPosition < sal_Int32( m_aFilterRows.size() - 1 ) )
+ ++m_nCurrentFilterPosition;
+ else
+ --m_nCurrentFilterPosition;
+ }
+
+ FmFilterRows::iterator pos = m_aFilterRows.begin() + _Term;
+ m_aFilterRows.erase( pos );
+
+ // adjust m_nCurrentFilterPosition if the removed row preceeded it
+ if ( _Term < m_nCurrentFilterPosition )
+ --m_nCurrentFilterPosition;
+
+ OSL_POSTCOND( ( m_nCurrentFilterPosition < 0 ) == ( m_aFilterRows.empty() ),
+ "FormController::removeDisjunctiveTerm: inconsistency!" );
+
+ // update the texts in the filter controls
+ impl_setTextOnAllFilter_throw();
+
+ FilterEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.DisjunctiveTerm = _Term;
+ aGuard.clear();
+ // <-- SYNCHRONIZED
+
+ m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved, aEvent );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::appendEmptyDisjunctiveTerm() throw (RuntimeException)
+{
+ // SYNCHRONIZED -->
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ impl_appendEmptyFilterRow( aGuard );
+ // <-- SYNCHRONIZED
+}
+
+//------------------------------------------------------------------------------
+::sal_Int32 SAL_CALL FormController::getActiveTerm() throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ return m_nCurrentFilterPosition;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::setActiveTerm( ::sal_Int32 _ActiveTerm ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if ( ( _ActiveTerm < 0 ) || ( _ActiveTerm >= getDisjunctiveTerms() ) )
+ throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
+
+ if ( _ActiveTerm == getActiveTerm() )
+ return;
+
+ m_nCurrentFilterPosition = _ActiveTerm;
+ impl_setTextOnAllFilter_throw();
+}
+
+// XElementAccess
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::hasElements(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return !m_aChilds.empty();
+}
+
+//------------------------------------------------------------------------------
+Type SAL_CALL FormController::getElementType(void) throw( RuntimeException )
+{
+ return ::getCppuType((const Reference< XFormController>*)0);
+
+}
+
+// XEnumerationAccess
+//------------------------------------------------------------------------------
+Reference< XEnumeration > SAL_CALL FormController::createEnumeration(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return new ::comphelper::OEnumerationByIndex(this);
+}
+
+// XIndexAccess
+//------------------------------------------------------------------------------
+sal_Int32 SAL_CALL FormController::getCount(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_aChilds.size();
+}
+
+//------------------------------------------------------------------------------
+Any SAL_CALL FormController::getByIndex(sal_Int32 Index) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (Index < 0 ||
+ Index >= (sal_Int32)m_aChilds.size())
+ throw IndexOutOfBoundsException();
+
+ return makeAny( m_aChilds[ Index ] );
+}
+
+// EventListener
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::disposing(const EventObject& e) throw( RuntimeException )
+{
+ // Ist der Container disposed worden
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XControlContainer > xContainer(e.Source, UNO_QUERY);
+ if (xContainer.is())
+ {
+ setContainer(Reference< XControlContainer > ());
+ }
+ else
+ {
+ // ist ein Control disposed worden
+ Reference< XControl > xControl(e.Source, UNO_QUERY);
+ if (xControl.is())
+ {
+ if (getContainer().is())
+ removeControl(xControl);
+ }
+ }
+}
+
+// OComponentHelper
+//-----------------------------------------------------------------------------
+void FormController::disposeAllFeaturesAndDispatchers() SAL_THROW(())
+{
+ for ( DispatcherContainer::iterator aDispatcher = m_aFeatureDispatchers.begin();
+ aDispatcher != m_aFeatureDispatchers.end();
+ ++aDispatcher
+ )
+ {
+ try
+ {
+ ::comphelper::disposeComponent( aDispatcher->second );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ m_aFeatureDispatchers.clear();
+}
+
+//-----------------------------------------------------------------------------
+void FormController::disposing(void)
+{
+ EventObject aEvt( *this );
+
+ // if we're still active, simulate a "deactivated" event
+ if ( m_xActiveControl.is() )
+ m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvt );
+
+ // notify all our listeners
+ m_aActivateListeners.disposeAndClear(aEvt);
+ m_aModifyListeners.disposeAndClear(aEvt);
+ m_aErrorListeners.disposeAndClear(aEvt);
+ m_aDeleteListeners.disposeAndClear(aEvt);
+ m_aRowSetApproveListeners.disposeAndClear(aEvt);
+ m_aParameterListeners.disposeAndClear(aEvt);
+ m_aFilterListeners.disposeAndClear(aEvt);
+
+ removeBoundFieldListener();
+ stopFiltering();
+
+ m_pControlBorderManager->restoreAll();
+
+ m_aFilterRows.clear();
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ m_xActiveControl = NULL;
+ implSetCurrentControl( NULL );
+
+ // clean up our children
+ for (FmFormControllers::const_iterator i = m_aChilds.begin();
+ i != m_aChilds.end(); ++i)
+ {
+ // search the position of the model within the form
+ Reference< XFormComponent > xForm((*i)->getModel(), UNO_QUERY);
+ sal_uInt32 nPos = m_xModelAsIndex->getCount();
+ Reference< XFormComponent > xTemp;
+ for( ; nPos; )
+ {
+
+ m_xModelAsIndex->getByIndex( --nPos ) >>= xTemp;
+ if ( xForm.get() == xTemp.get() )
+ {
+ Reference< XInterface > xIfc( *i, UNO_QUERY );
+ m_xModelAsManager->detach( nPos, xIfc );
+ break;
+ }
+ }
+
+ Reference< XComponent > (*i, UNO_QUERY)->dispose();
+ }
+ m_aChilds.clear();
+
+ disposeAllFeaturesAndDispatchers();
+
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->dispose();
+ m_xFormOperations.clear();
+
+ if (m_bDBConnection)
+ unload();
+
+ setContainer( NULL );
+ setModel( NULL );
+ setParent( NULL );
+
+ ::comphelper::disposeComponent( m_xComposer );
+
+ m_bDBConnection = sal_False;
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ static bool lcl_shouldUseDynamicControlBorder( const Reference< XInterface >& _rxForm, const Any& _rDynamicColorProp )
+ {
+ bool bDoUse = false;
+ if ( !( _rDynamicColorProp >>= bDoUse ) )
+ {
+ DocumentType eDocType = DocumentClassification::classifyHostDocument( _rxForm );
+ return ControlLayouter::useDynamicBorderColor( eDocType );
+ }
+ return bDoUse;
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ if ( evt.PropertyName == FM_PROP_BOUNDFIELD )
+ {
+ Reference<XPropertySet> xOldBound;
+ evt.OldValue >>= xOldBound;
+ if ( !xOldBound.is() && evt.NewValue.hasValue() )
+ {
+ Reference< XControlModel > xControlModel(evt.Source,UNO_QUERY);
+ Reference< XControl > xControl = findControl(m_aControls,xControlModel,sal_False,sal_False);
+ if ( xControl.is() )
+ {
+ startControlModifyListening( xControl );
+ Reference<XPropertySet> xProp(xControlModel,UNO_QUERY);
+ if ( xProp.is() )
+ xProp->removePropertyChangeListener(FM_PROP_BOUNDFIELD, this);
+ }
+ }
+ }
+ else
+ {
+ sal_Bool bModifiedChanged = (evt.PropertyName == FM_PROP_ISMODIFIED);
+ sal_Bool bNewChanged = (evt.PropertyName == FM_PROP_ISNEW);
+ if (bModifiedChanged || bNewChanged)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (bModifiedChanged)
+ m_bCurrentRecordModified = ::comphelper::getBOOL(evt.NewValue);
+ else
+ m_bCurrentRecordNew = ::comphelper::getBOOL(evt.NewValue);
+
+ // toggle the locking
+ if (m_bLocked != determineLockState())
+ {
+ m_bLocked = !m_bLocked;
+ setLocks();
+ if (isListeningForChanges())
+ startListening();
+ else
+ stopListening();
+ }
+
+ if ( bNewChanged )
+ m_aToggleEvent.Call();
+
+ if (!m_bCurrentRecordModified)
+ m_bModified = sal_False;
+ }
+ else if ( evt.PropertyName == FM_PROP_DYNAMIC_CONTROL_BORDER )
+ {
+ bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
+ if ( bEnable )
+ {
+ m_pControlBorderManager->enableDynamicBorderColor();
+ if ( m_xActiveControl.is() )
+ m_pControlBorderManager->focusGained( m_xActiveControl.get() );
+ }
+ else
+ {
+ m_pControlBorderManager->disableDynamicBorderColor();
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+bool FormController::replaceControl( const Reference< XControl >& _rxExistentControl, const Reference< XControl >& _rxNewControl )
+{
+ bool bSuccess = false;
+ try
+ {
+ Reference< XIdentifierReplace > xContainer( getContainer(), UNO_QUERY );
+ DBG_ASSERT( xContainer.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
+ if ( xContainer.is() )
+ {
+ // look up the ID of _rxExistentControl
+ Sequence< sal_Int32 > aIdentifiers( xContainer->getIdentifiers() );
+ const sal_Int32* pIdentifiers = aIdentifiers.getConstArray();
+ const sal_Int32* pIdentifiersEnd = aIdentifiers.getConstArray() + aIdentifiers.getLength();
+ for ( ; pIdentifiers != pIdentifiersEnd; ++pIdentifiers )
+ {
+ Reference< XControl > xCheck( xContainer->getByIdentifier( *pIdentifiers ), UNO_QUERY );
+ if ( xCheck == _rxExistentControl )
+ break;
+ }
+ DBG_ASSERT( pIdentifiers != pIdentifiersEnd, "FormController::replaceControl: did not find the control in the container!" );
+ if ( pIdentifiers != pIdentifiersEnd )
+ {
+ bool bReplacedWasActive = ( m_xActiveControl.get() == _rxExistentControl.get() );
+ bool bReplacedWasCurrent = ( m_xCurrentControl.get() == _rxExistentControl.get() );
+
+ if ( bReplacedWasActive )
+ {
+ m_xActiveControl = NULL;
+ implSetCurrentControl( NULL );
+ }
+ else if ( bReplacedWasCurrent )
+ {
+ implSetCurrentControl( _rxNewControl );
+ }
+
+ // carry over the model
+ _rxNewControl->setModel( _rxExistentControl->getModel() );
+
+ xContainer->replaceByIdentifer( *pIdentifiers, makeAny( _rxNewControl ) );
+ bSuccess = true;
+
+ if ( bReplacedWasActive )
+ {
+ Reference< XWindow > xControlWindow( _rxNewControl, UNO_QUERY );
+ if ( xControlWindow.is() )
+ xControlWindow->setFocus();
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ Reference< XControl > xDisposeIt( bSuccess ? _rxExistentControl : _rxNewControl );
+ ::comphelper::disposeComponent( xDisposeIt );
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------------
+void FormController::toggleAutoFields(sal_Bool bAutoFields)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+
+ Sequence< Reference< XControl > > aControlsCopy( m_aControls );
+ const Reference< XControl >* pControls = aControlsCopy.getConstArray();
+ sal_Int32 nControls = aControlsCopy.getLength();
+
+ if (bAutoFields)
+ {
+ // as we don't want new controls to be attached to the scripting environment
+ // we change attach flags
+ m_bAttachEvents = sal_False;
+ for (sal_Int32 i = nControls; i > 0;)
+ {
+ Reference< XControl > xControl = pControls[--i];
+ if (xControl.is())
+ {
+ Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // does the model use a bound field ?
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+
+ // is it a autofield?
+ if ( xField.is()
+ && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
+ && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_AUTOINCREMENT ) )
+ )
+ {
+ replaceControl( xControl, new FmXAutoControl );
+ }
+ }
+ }
+ }
+ m_bAttachEvents = sal_True;
+ }
+ else
+ {
+ m_bDetachEvents = sal_False;
+ for (sal_Int32 i = nControls; i > 0;)
+ {
+ Reference< XControl > xControl = pControls[--i];
+ if (xControl.is())
+ {
+ Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // does the model use a bound field ?
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+
+ // is it a autofield?
+ if ( xField.is()
+ && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
+ && ::comphelper::getBOOL( xField->getPropertyValue(FM_PROP_AUTOINCREMENT ) )
+ )
+ {
+ ::rtl::OUString sServiceName;
+ OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
+ Reference< XControl > xNewControl( m_aContext.createComponent( sServiceName ), UNO_QUERY );
+ replaceControl( xControl, xNewControl );
+ }
+ }
+ }
+ }
+ m_bDetachEvents = sal_True;
+ }
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FormController, OnToggleAutoFields, void*, EMPTYARG)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ toggleAutoFields(m_bCurrentRecordNew);
+ return 1L;
+}
+
+// XTextListener
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::textChanged(const TextEvent& e) throw( RuntimeException )
+{
+ // SYNCHRONIZED -->
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ if (m_bFiltering)
+ {
+ Reference< XTextComponent > xText(e.Source,UNO_QUERY);
+ ::rtl::OUString aText = xText->getText();
+
+ if ( m_aFilterRows.empty() )
+ appendEmptyDisjunctiveTerm();
+
+ // Suchen der aktuellen Row
+ if ( ( (size_t)m_nCurrentFilterPosition >= m_aFilterRows.size() ) || ( m_nCurrentFilterPosition < 0 ) )
+ {
+ OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
+ return;
+ }
+
+ FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
+
+ // do we have a new filter
+ if (aText.getLength())
+ rRow[xText] = aText;
+ else
+ {
+ // do we have the control in the row
+ FmFilterRow::iterator iter = rRow.find(xText);
+ // erase the entry out of the row
+ if (iter != rRow.end())
+ rRow.erase(iter);
+ }
+
+ // multiplex the event to our FilterControllerListeners
+ FilterEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.FilterComponent = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xText ) - m_aFilterComponents.begin();
+ aEvent.DisjunctiveTerm = getActiveTerm();
+ aEvent.PredicateExpression = aText;
+
+ aGuard.clear();
+ // <-- SYNCHRONIZED
+
+ // notify the changed filter expression
+ m_aFilterListeners.notifyEach( &XFilterControllerListener::predicateExpressionChanged, aEvent );
+ }
+ else
+ impl_onModify();
+}
+
+// XItemListener
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::itemStateChanged(const ItemEvent& /*rEvent*/) throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ impl_onModify();
+}
+
+// XModificationBroadcaster
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_aModifyListeners.addInterface( l );
+}
+
+//------------------------------------------------------------------------------
+void FormController::removeModifyListener(const Reference< XModifyListener > & l) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_aModifyListeners.removeInterface( l );
+}
+
+// XModificationListener
+//------------------------------------------------------------------------------
+void FormController::modified( const EventObject& _rEvent ) throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ try
+ {
+ if ( _rEvent.Source != m_xActiveControl )
+ { // let this control grab the focus
+ // (this case may happen if somebody moves the scroll wheel of the mouse over a control
+ // which does not have the focus)
+ // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
+ //
+ // also, it happens when an image control gets a new image by double-clicking it
+ // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
+ Reference< XWindow > xControlWindow( _rEvent.Source, UNO_QUERY_THROW );
+ xControlWindow->setFocus();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ impl_onModify();
+}
+
+//------------------------------------------------------------------------------
+void FormController::impl_checkDisposed_throw() const
+{
+ if ( impl_isDisposed_nofail() )
+ throw DisposedException( ::rtl::OUString(), *const_cast< FormController* >( this ) );
+}
+
+//------------------------------------------------------------------------------
+void FormController::impl_onModify()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_bModified )
+ m_bModified = sal_True;
+ }
+
+ EventObject aEvt(static_cast<cppu::OWeakObject*>(this));
+ m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
+}
+
+//------------------------------------------------------------------------------
+void FormController::impl_addFilterRow( const FmFilterRow& _row )
+{
+ m_aFilterRows.push_back( _row );
+
+ if ( m_aFilterRows.size() == 1 )
+ { // that's the first row ever
+ OSL_ENSURE( m_nCurrentFilterPosition == -1, "FormController::impl_addFilterRow: inconsistency!" );
+ m_nCurrentFilterPosition = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard& _rClearBeforeNotify )
+{
+ // SYNCHRONIZED -->
+ impl_addFilterRow( FmFilterRow() );
+
+ // notify the listeners
+ FilterEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.DisjunctiveTerm = (sal_Int32)m_aFilterRows.size() - 1;
+ _rClearBeforeNotify.clear();
+ // <-- SYNCHRONIZED
+ m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermAdded, aEvent );
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FormController::determineLockState() const
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ // a.) in filter mode we are always locked
+ // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
+ // c.) if we are inserting everything is OK and we are not locked
+ // d.) if are not updatable or on invalid position
+ Reference< XResultSet > xResultSet(m_xModelAsIndex, UNO_QUERY);
+ if (m_bFiltering || !xResultSet.is() || !isRowSetAlive(xResultSet))
+ return sal_True;
+ else
+ return (m_bCanInsert && m_bCurrentRecordNew) ? sal_False
+ : xResultSet->isBeforeFirst() || xResultSet->isAfterLast() || xResultSet->rowDeleted() || !m_bCanUpdate;
+}
+
+// FocusListener
+//------------------------------------------------------------------------------
+void FormController::focusGained(const FocusEvent& e) throw( RuntimeException )
+{
+ // SYNCHRONIZED -->
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_pControlBorderManager->focusGained( e.Source );
+
+ Reference< XControl > xControl(e.Source, UNO_QUERY);
+ if (m_bDBConnection)
+ {
+ // do we need to keep the locking of the commit
+ // we hold the lock as long as the control differs from the current
+ // otherwhise we disabled the lock
+ m_bCommitLock = m_bCommitLock && (XControl*)xControl.get() != (XControl*)m_xCurrentControl.get();
+ if (m_bCommitLock)
+ return;
+
+ // when do we have to commit a value to form or a filter
+ // a.) if the current value is modified
+ // b.) there must be a current control
+ // c.) and it must be different from the new focus owning control or
+ // d.) the focus is moving around (so we have only one control)
+
+ if ( ( m_bModified || m_bFiltering )
+ && m_xCurrentControl.is()
+ && ( ( xControl.get() != m_xCurrentControl.get() )
+ || ( ( e.FocusFlags & FocusChangeReason::AROUND )
+ && ( m_bCycle || m_bFiltering )
+ )
+ )
+ )
+ {
+ // check the old control if the content is ok
+#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
+ Reference< XBoundControl > xLockingTest(m_xCurrentControl, UNO_QUERY);
+ sal_Bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
+ OSL_ENSURE(!bControlIsLocked, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
+ // normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
+ // gesetzt worden sein, was ich nicht verstehen wuerde ...
+#endif
+ DBG_ASSERT(m_xCurrentControl.is(), "kein CurrentControl gesetzt");
+ // zunaechst das Control fragen ob es das IFace unterstuetzt
+ Reference< XBoundComponent > xBound(m_xCurrentControl, UNO_QUERY);
+ if (!xBound.is() && m_xCurrentControl.is())
+ xBound = Reference< XBoundComponent > (m_xCurrentControl->getModel(), UNO_QUERY);
+
+ // lock if we lose the focus during commit
+ m_bCommitLock = sal_True;
+
+ // Commit nicht erfolgreich, Focus zuruecksetzen
+ if (xBound.is() && !xBound->commit())
+ {
+ // the commit failed and we don't commit again until the current control
+ // which couldn't be commit gains the focus again
+ Reference< XWindow > xWindow(m_xCurrentControl, UNO_QUERY);
+ if (xWindow.is())
+ xWindow->setFocus();
+ return;
+ }
+ else
+ {
+ m_bModified = sal_False;
+ m_bCommitLock = sal_False;
+ }
+ }
+
+ if (!m_bFiltering && m_bCycle && (e.FocusFlags & FocusChangeReason::AROUND) && m_xCurrentControl.is())
+ {
+ SQLErrorEvent aErrorEvent;
+ OSL_ENSURE( m_xFormOperations.is(), "FormController::focusGained: hmm?" );
+ // should have been created in setModel
+ try
+ {
+ if ( e.FocusFlags & FocusChangeReason::FORWARD )
+ {
+ if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToNext ) )
+ m_xFormOperations->execute( FormFeature::MoveToNext );
+ }
+ else // backward
+ {
+ if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToPrevious ) )
+ m_xFormOperations->execute( FormFeature::MoveToPrevious );
+ }
+ }
+ catch ( const Exception& )
+ {
+ // don't handle this any further. That's an ... admissible error.
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+
+ // Immer noch ein und dasselbe Control
+ if ( ( m_xActiveControl == xControl )
+ && ( xControl == m_xCurrentControl )
+ )
+ {
+ DBG_ASSERT(m_xCurrentControl.is(), "Kein CurrentControl selektiert");
+ return;
+ }
+
+ sal_Bool bActivated = !m_xActiveControl.is() && xControl.is();
+
+ m_xActiveControl = xControl;
+
+ implSetCurrentControl( xControl );
+ OSL_POSTCOND( m_xCurrentControl.is(), "implSetCurrentControl did nonsense!" );
+
+ if ( bActivated )
+ {
+ // (asynchronously) call activation handlers
+ m_aActivationEvent.Call();
+
+ // call modify listeners
+ if ( m_bModified )
+ m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) );
+ }
+
+ // invalidate all features which depend on the currently focused control
+ if ( m_bDBConnection && !m_bFiltering )
+ implInvalidateCurrentControlDependentFeatures();
+
+ if ( !m_xCurrentControl.is() )
+ return;
+
+ // Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
+ Reference< XFormControllerContext > xContext( m_xContext );
+ Reference< XControl > xCurrentControl( m_xCurrentControl );
+ aGuard.clear();
+ // <-- SYNCHRONIZED
+
+ if ( xContext.is() )
+ xContext->makeVisible( xCurrentControl );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK( FormController, OnActivated, void*, /**/ )
+{
+ EventObject aEvent;
+ aEvent.Source = *this;
+ m_aActivateListeners.notifyEach( &XFormControllerListener::formActivated, aEvent );
+
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK( FormController, OnDeactivated, void*, /**/ )
+{
+ EventObject aEvent;
+ aEvent.Source = *this;
+ m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvent );
+
+ return 0L;
+}
+
+//------------------------------------------------------------------------------
+void FormController::focusLost(const FocusEvent& e) throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ m_pControlBorderManager->focusLost( e.Source );
+
+ Reference< XControl > xControl(e.Source, UNO_QUERY);
+ Reference< XWindowPeer > xNext(e.NextFocus, UNO_QUERY);
+ Reference< XControl > xNextControl = isInList(xNext);
+ if (!xNextControl.is())
+ {
+ m_xActiveControl = NULL;
+ m_aDeactivationEvent.Call();
+ }
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException)
+{
+ // not interested in
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ ) throw (RuntimeException)
+{
+ // not interested in
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent ) throw (RuntimeException)
+{
+ m_pControlBorderManager->mouseEntered( _rEvent.Source );
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent ) throw (RuntimeException)
+{
+ m_pControlBorderManager->mouseExited( _rEvent.Source );
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSource ) throw (RuntimeException)
+{
+ Reference< XControl > xControl( findControl( m_aControls, Reference< XControlModel >( _rSource.Source, UNO_QUERY ), sal_False, sal_False ) );
+ Reference< XValidatableFormComponent > xValidatable( _rSource.Source, UNO_QUERY );
+
+ OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" );
+
+ if ( xControl.is() && xValidatable.is() )
+ m_pControlBorderManager->validityChanged( xControl, xValidatable );
+}
+
+//--------------------------------------------------------------------
+void FormController::setModel(const Reference< XTabControllerModel > & Model) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::setModel : invalid aggregate !");
+
+ try
+ {
+ // disconnect from the old model
+ if (m_xModelAsIndex.is())
+ {
+ if (m_bDBConnection)
+ {
+ // we are currently working on the model
+ EventObject aEvt(m_xModelAsIndex);
+ unloaded(aEvt);
+ }
+
+ Reference< XLoadable > xForm(m_xModelAsIndex, UNO_QUERY);
+ if (xForm.is())
+ xForm->removeLoadListener(this);
+
+ Reference< XSQLErrorBroadcaster > xBroadcaster(m_xModelAsIndex, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeSQLErrorListener(this);
+
+ Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(m_xModelAsIndex, UNO_QUERY);
+ if (xParamBroadcaster.is())
+ xParamBroadcaster->removeParameterListener(this);
+
+ }
+
+ disposeAllFeaturesAndDispatchers();
+
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->dispose();
+ m_xFormOperations.clear();
+
+ // set the new model wait for the load event
+ if (m_xTabController.is())
+ m_xTabController->setModel(Model);
+ m_xModelAsIndex = Reference< XIndexAccess > (Model, UNO_QUERY);
+ m_xModelAsManager = Reference< XEventAttacherManager > (Model, UNO_QUERY);
+
+ // only if both ifaces exit, the controller will work successful
+ if (!m_xModelAsIndex.is() || !m_xModelAsManager.is())
+ {
+ m_xModelAsManager = NULL;
+ m_xModelAsIndex = NULL;
+ }
+
+ if (m_xModelAsIndex.is())
+ {
+ // re-create m_xFormOperations
+ m_xFormOperations.set( FormOperations::createWithFormController( m_aContext.getUNOContext(), this ), UNO_SET_THROW );
+ m_xFormOperations->setFeatureInvalidation( this );
+
+ // adding load and ui interaction listeners
+ Reference< XLoadable > xForm(Model, UNO_QUERY);
+ if (xForm.is())
+ xForm->addLoadListener(this);
+
+ Reference< XSQLErrorBroadcaster > xBroadcaster(Model, UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->addSQLErrorListener(this);
+
+ Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(Model, UNO_QUERY);
+ if (xParamBroadcaster.is())
+ xParamBroadcaster->addParameterListener(this);
+
+ // well, is the database already loaded?
+ // then we have to simulate a load event
+ Reference< XLoadable > xCursor(m_xModelAsIndex, UNO_QUERY);
+ if (xCursor.is() && xCursor->isLoaded())
+ {
+ EventObject aEvt(xCursor);
+ loaded(aEvt);
+ }
+
+ Reference< XPropertySet > xModelProps( m_xModelAsIndex, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropInfo( xModelProps->getPropertySetInfo() );
+ if ( xPropInfo.is()
+ && xPropInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER )
+ && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS )
+ && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE )
+ && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID )
+ )
+ {
+ bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
+ xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER ) );
+ if ( bEnableDynamicControlBorder )
+ m_pControlBorderManager->enableDynamicBorderColor();
+ else
+ m_pControlBorderManager->disableDynamicBorderColor();
+
+ sal_Int32 nColor = 0;
+ if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS ) >>= nColor )
+ m_pControlBorderManager->setStatusColor( CONTROL_STATUS_FOCUSED, nColor );
+ if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE ) >>= nColor )
+ m_pControlBorderManager->setStatusColor( CONTROL_STATUS_MOUSE_HOVER, nColor );
+ if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID ) >>= nColor )
+ m_pControlBorderManager->setStatusColor( CONTROL_STATUS_INVALID, nColor );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XTabControllerModel > FormController::getModel() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::getModel : invalid aggregate !");
+ if (!m_xTabController.is())
+ return Reference< XTabControllerModel > ();
+ return m_xTabController->getModel();
+}
+
+//------------------------------------------------------------------------------
+void FormController::addToEventAttacher(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ OSL_ENSURE( xControl.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
+ if ( !xControl.is() )
+ return; /* throw IllegalArgumentException(); */
+
+ // anmelden beim Eventattacher
+ Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
+ if (xComp.is() && m_xModelAsIndex.is())
+ {
+ // Und die Position des ControlModel darin suchen
+ sal_uInt32 nPos = m_xModelAsIndex->getCount();
+ Reference< XFormComponent > xTemp;
+ for( ; nPos; )
+ {
+ m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
+ if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
+ {
+ Reference< XInterface > xIfc(xControl, UNO_QUERY);
+ m_xModelAsManager->attach( nPos, xIfc, makeAny(xControl) );
+ break;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::removeFromEventAttacher(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ OSL_ENSURE( xControl.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
+ if ( !xControl.is() )
+ return; /* throw IllegalArgumentException(); */
+
+ // abmelden beim Eventattacher
+ Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
+ if ( xComp.is() && m_xModelAsIndex.is() )
+ {
+ // Und die Position des ControlModel darin suchen
+ sal_uInt32 nPos = m_xModelAsIndex->getCount();
+ Reference< XFormComponent > xTemp;
+ for( ; nPos; )
+ {
+ m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
+ if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
+ {
+ Reference< XInterface > xIfc(xControl, UNO_QUERY);
+ m_xModelAsManager->detach( nPos, xIfc );
+ break;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::setContainer(const Reference< XControlContainer > & xContainer) throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ Reference< XTabControllerModel > xTabModel(getModel());
+ DBG_ASSERT(xTabModel.is() || !xContainer.is(), "No Model defined");
+ // if we have a new container we need a model
+ DBG_ASSERT(m_xTabController.is(), "FormController::setContainer : invalid aggregate !");
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XContainer > xCurrentContainer;
+ if (m_xTabController.is())
+ xCurrentContainer = Reference< XContainer > (m_xTabController->getContainer(), UNO_QUERY);
+ if (xCurrentContainer.is())
+ {
+ xCurrentContainer->removeContainerListener(this);
+
+ if ( m_aTabActivationTimer.IsActive() )
+ m_aTabActivationTimer.Stop();
+
+ // clear the filter map
+ ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
+ m_aFilterComponents.clear();
+
+ // einsammeln der Controls
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ implControlRemoved( *pControls++, true );
+
+ // Datenbank spezifische Dinge vornehmen
+ if (m_bDBConnection && isListeningForChanges())
+ stopListening();
+
+ m_aControls.realloc( 0 );
+ }
+
+ if (m_xTabController.is())
+ m_xTabController->setContainer(xContainer);
+
+ // Welche Controls gehoeren zum Container ?
+ if (xContainer.is() && xTabModel.is())
+ {
+ Sequence< Reference< XControlModel > > aModels = xTabModel->getControlModels();
+ const Reference< XControlModel > * pModels = aModels.getConstArray();
+ Sequence< Reference< XControl > > aAllControls = xContainer->getControls();
+
+ sal_Int32 nCount = aModels.getLength();
+ m_aControls = Sequence< Reference< XControl > >( nCount );
+ Reference< XControl > * pControls = m_aControls.getArray();
+
+ // einsammeln der Controls
+ sal_Int32 i, j;
+ for (i = 0, j = 0; i < nCount; ++i, ++pModels )
+ {
+ Reference< XControl > xControl = findControl( aAllControls, *pModels, sal_False, sal_True );
+ if ( xControl.is() )
+ {
+ pControls[j++] = xControl;
+ implControlInserted( xControl, true );
+ }
+ }
+
+ // not every model had an associated control
+ if (j != i)
+ m_aControls.realloc(j);
+
+ // am Container horchen
+ Reference< XContainer > xNewContainer(xContainer, UNO_QUERY);
+ if (xNewContainer.is())
+ xNewContainer->addContainerListener(this);
+
+ // Datenbank spezifische Dinge vornehmen
+ if (m_bDBConnection)
+ {
+ m_bLocked = determineLockState();
+ setLocks();
+ if (!isLocked())
+ startListening();
+ }
+ }
+ // befinden sich die Controls in der richtigen Reihenfolge
+ m_bControlsSorted = sal_True;
+}
+
+//------------------------------------------------------------------------------
+Reference< XControlContainer > FormController::getContainer() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::getContainer : invalid aggregate !");
+ if (!m_xTabController.is())
+ return Reference< XControlContainer > ();
+ return m_xTabController->getContainer();
+}
+
+//------------------------------------------------------------------------------
+Sequence< Reference< XControl > > FormController::getControls(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if (!m_bControlsSorted)
+ {
+ Reference< XTabControllerModel > xModel = getModel();
+ if (!xModel.is())
+ return m_aControls;
+
+ Sequence< Reference< XControlModel > > aControlModels = xModel->getControlModels();
+ const Reference< XControlModel > * pModels = aControlModels.getConstArray();
+ sal_Int32 nModels = aControlModels.getLength();
+
+ Sequence< Reference< XControl > > aNewControls(nModels);
+
+ Reference< XControl > * pControls = aNewControls.getArray();
+ Reference< XControl > xControl;
+
+ // Umsortieren der Controls entsprechend der TabReihenfolge
+ sal_Int32 j = 0;
+ for (sal_Int32 i = 0; i < nModels; ++i, ++pModels )
+ {
+ xControl = findControl( m_aControls, *pModels, sal_True, sal_True );
+ if ( xControl.is() )
+ pControls[j++] = xControl;
+ }
+
+ // not every model had an associated control
+ if ( j != nModels )
+ aNewControls.realloc( j );
+
+ m_aControls = aNewControls;
+ m_bControlsSorted = sal_True;
+ }
+ return m_aControls;
+}
+
+//------------------------------------------------------------------------------
+void FormController::autoTabOrder() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::autoTabOrder : invalid aggregate !");
+ if (m_xTabController.is())
+ m_xTabController->autoTabOrder();
+}
+
+//------------------------------------------------------------------------------
+void FormController::activateTabOrder() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::activateTabOrder : invalid aggregate !");
+ if (m_xTabController.is())
+ m_xTabController->activateTabOrder();
+}
+
+//------------------------------------------------------------------------------
+void FormController::setControlLock(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ sal_Bool bLocked = isLocked();
+
+ // es wird gelockt
+ // a.) wenn der ganze Datensatz gesperrt ist
+ // b.) wenn das zugehoerige Feld gespeert ist
+ Reference< XBoundControl > xBound(xControl, UNO_QUERY);
+ if (xBound.is() && (( (bLocked && bLocked != xBound->getLock()) ||
+ !bLocked))) // beim entlocken immer einzelne Felder ueberprüfen
+ {
+ // gibt es eine Datenquelle
+ Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // wie sieht mit den Properties ReadOnly und Enable aus
+ sal_Bool bTouch = sal_True;
+ if (::comphelper::hasProperty(FM_PROP_ENABLED, xSet))
+ bTouch = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ENABLED));
+ if (::comphelper::hasProperty(FM_PROP_READONLY, xSet))
+ bTouch = !::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_READONLY));
+
+ if (bTouch)
+ {
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+ if (xField.is())
+ {
+ if (bLocked)
+ xBound->setLock(bLocked);
+ else
+ {
+ try
+ {
+ Any aVal = xField->getPropertyValue(FM_PROP_ISREADONLY);
+ if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
+ xBound->setLock(sal_True);
+ else
+ xBound->setLock(bLocked);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ }
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::setLocks()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ // alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ setControlLock( *pControls++ );
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ bool lcl_shouldListenForModifications( const Reference< XControl >& _rxControl, const Reference< XPropertyChangeListener >& _rxBoundFieldListener )
+ {
+ bool bShould = false;
+
+ Reference< XBoundComponent > xBound( _rxControl, UNO_QUERY );
+ if ( xBound.is() )
+ {
+ bShould = true;
+ }
+ else if ( _rxControl.is() )
+ {
+ Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
+ if ( xModelProps.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD, xModelProps ) )
+ {
+ Reference< XPropertySet > xField;
+ xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
+ bShould = xField.is();
+
+ if ( !bShould && _rxBoundFieldListener.is() )
+ xModelProps->addPropertyChangeListener( FM_PROP_BOUNDFIELD, _rxBoundFieldListener );
+ }
+ }
+
+ return bShould;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::startControlModifyListening(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ bool bModifyListening = lcl_shouldListenForModifications( xControl, this );
+
+ // artificial while
+ while ( bModifyListening )
+ {
+ Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
+ if (xMod.is())
+ {
+ xMod->addModifyListener(this);
+ break;
+ }
+
+ // alle die Text um vorzeitig ein modified zu erkennen
+ Reference< XTextComponent > xText(xControl, UNO_QUERY);
+ if (xText.is())
+ {
+ xText->addTextListener(this);
+ break;
+ }
+
+ Reference< XCheckBox > xBox(xControl, UNO_QUERY);
+ if (xBox.is())
+ {
+ xBox->addItemListener(this);
+ break;
+ }
+
+ Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
+ if (xCbBox.is())
+ {
+ xCbBox->addItemListener(this);
+ break;
+ }
+
+ Reference< XListBox > xListBox(xControl, UNO_QUERY);
+ if (xListBox.is())
+ {
+ xListBox->addItemListener(this);
+ break;
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::stopControlModifyListening(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ bool bModifyListening = lcl_shouldListenForModifications( xControl, NULL );
+
+ // kuenstliches while
+ while (bModifyListening)
+ {
+ Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
+ if (xMod.is())
+ {
+ xMod->removeModifyListener(this);
+ break;
+ }
+ // alle die Text um vorzeitig ein modified zu erkennen
+ Reference< XTextComponent > xText(xControl, UNO_QUERY);
+ if (xText.is())
+ {
+ xText->removeTextListener(this);
+ break;
+ }
+
+ Reference< XCheckBox > xBox(xControl, UNO_QUERY);
+ if (xBox.is())
+ {
+ xBox->removeItemListener(this);
+ break;
+ }
+
+ Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
+ if (xCbBox.is())
+ {
+ xCbBox->removeItemListener(this);
+ break;
+ }
+
+ Reference< XListBox > xListBox(xControl, UNO_QUERY);
+ if (xListBox.is())
+ {
+ xListBox->removeItemListener(this);
+ break;
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::startListening()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ m_bModified = sal_False;
+
+ // jetzt anmelden bei gebundenen feldern
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ startControlModifyListening( *pControls++ );
+}
+
+//------------------------------------------------------------------------------
+void FormController::stopListening()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ m_bModified = sal_False;
+
+ // jetzt anmelden bei gebundenen feldern
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ stopControlModifyListening( *pControls++ );
+}
+
+
+//------------------------------------------------------------------------------
+Reference< XControl > FormController::findControl(Sequence< Reference< XControl > >& _rControls, const Reference< XControlModel > & xCtrlModel ,sal_Bool _bRemove,sal_Bool _bOverWrite) const
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ DBG_ASSERT( xCtrlModel.is(), "findControl - welches ?!" );
+
+ Reference< XControl >* pControls = _rControls.getArray();
+ Reference< XControlModel > xModel;
+ for ( sal_Int32 i = 0, nCount = _rControls.getLength(); i < nCount; ++i, ++pControls )
+ {
+ if ( pControls->is() )
+ {
+ xModel = (*pControls)->getModel();
+ if ( xModel.get() == xCtrlModel.get() )
+ {
+ Reference< XControl > xControl( *pControls );
+ if ( _bRemove )
+ ::comphelper::removeElementAt( _rControls, i );
+ else if ( _bOverWrite )
+ *pControls = Reference< XControl >();
+ return xControl;
+ }
+ }
+ }
+ return Reference< XControl > ();
+}
+
+//------------------------------------------------------------------------------
+void FormController::implControlInserted( const Reference< XControl>& _rxControl, bool _bAddToEventAttacher )
+{
+ Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
+ if ( xWindow.is() )
+ {
+ xWindow->addFocusListener( this );
+ xWindow->addMouseListener( this );
+
+ if ( _bAddToEventAttacher )
+ addToEventAttacher( _rxControl );
+ }
+
+ // add a dispatch interceptor to the control (if supported)
+ Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY );
+ if ( xInterception.is() )
+ createInterceptor( xInterception );
+
+ if ( _rxControl.is() )
+ {
+ Reference< XControlModel > xModel( _rxControl->getModel() );
+
+ // we want to know about the reset of the the model of our controls
+ // (for correctly resetting m_bModified)
+ Reference< XReset > xReset( xModel, UNO_QUERY );
+ if ( xReset.is() )
+ xReset->addResetListener( this );
+
+ // and we want to know about the validity, to visually indicate it
+ Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
+ if ( xValidatable.is() )
+ {
+ xValidatable->addFormComponentValidityListener( this );
+ m_pControlBorderManager->validityChanged( _rxControl, xValidatable );
+ }
+ }
+
+}
+
+//------------------------------------------------------------------------------
+void FormController::implControlRemoved( const Reference< XControl>& _rxControl, bool _bRemoveFromEventAttacher )
+{
+ Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
+ if ( xWindow.is() )
+ {
+ xWindow->removeFocusListener( this );
+ xWindow->removeMouseListener( this );
+
+ if ( _bRemoveFromEventAttacher )
+ removeFromEventAttacher( _rxControl );
+ }
+
+ Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY);
+ if ( xInterception.is() )
+ deleteInterceptor( xInterception );
+
+ if ( _rxControl.is() )
+ {
+ Reference< XControlModel > xModel( _rxControl->getModel() );
+
+ Reference< XReset > xReset( xModel, UNO_QUERY );
+ if ( xReset.is() )
+ xReset->removeResetListener( this );
+
+ Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
+ if ( xValidatable.is() )
+ xValidatable->removeFormComponentValidityListener( this );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::implSetCurrentControl( const Reference< XControl >& _rxControl )
+{
+ if ( m_xCurrentControl.get() == _rxControl.get() )
+ return;
+
+ Reference< XGridControl > xGridControl( m_xCurrentControl, UNO_QUERY );
+ if ( xGridControl.is() )
+ xGridControl->removeGridControlListener( this );
+
+ m_xCurrentControl = _rxControl;
+
+ xGridControl.set( m_xCurrentControl, UNO_QUERY );
+ if ( xGridControl.is() )
+ xGridControl->addGridControlListener( this );
+}
+
+//------------------------------------------------------------------------------
+void FormController::insertControl(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ m_bControlsSorted = sal_False;
+ m_aControls.realloc(m_aControls.getLength() + 1);
+ m_aControls.getArray()[m_aControls.getLength() - 1] = xControl;
+
+ if ( m_pColumnInfoCache.get() )
+ m_pColumnInfoCache->deinitializeControls();
+
+ implControlInserted( xControl, m_bAttachEvents );
+
+ if (m_bDBConnection && !m_bFiltering)
+ setControlLock(xControl);
+
+ if (isListeningForChanges() && m_bAttachEvents)
+ startControlModifyListening( xControl );
+}
+
+//------------------------------------------------------------------------------
+void FormController::removeControl(const Reference< XControl > & xControl)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ {
+ if ( xControl.get() == (*pControls++).get() )
+ {
+ ::comphelper::removeElementAt( m_aControls, pControls - m_aControls.getConstArray() - 1 );
+ break;
+ }
+ }
+
+ FilterComponents::iterator componentPos = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
+ if ( componentPos != m_aFilterComponents.end() )
+ m_aFilterComponents.erase( componentPos );
+
+ implControlRemoved( xControl, m_bDetachEvents );
+
+ if ( isListeningForChanges() && m_bDetachEvents )
+ stopControlModifyListening( xControl );
+}
+
+// XLoadListener
+//------------------------------------------------------------------------------
+void FormController::loaded(const EventObject& rEvent) throw( RuntimeException )
+{
+ OSL_ENSURE( rEvent.Source == m_xModelAsIndex, "FormController::loaded: where did this come from?" );
+
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XRowSet > xForm(rEvent.Source, UNO_QUERY);
+ // do we have a connected data source
+ OStaticDataAccessTools aStaticTools;
+ if (xForm.is() && aStaticTools.getRowSetConnection(xForm).is())
+ {
+ Reference< XPropertySet > xSet(xForm, UNO_QUERY);
+ if (xSet.is())
+ {
+ Any aVal = xSet->getPropertyValue(FM_PROP_CYCLE);
+ sal_Int32 aVal2 = 0;
+ ::cppu::enum2int(aVal2,aVal);
+ m_bCycle = !aVal.hasValue() || aVal2 == TabulatorCycle_RECORDS;
+ m_bCanUpdate = aStaticTools.canUpdate(xSet);
+ m_bCanInsert = aStaticTools.canInsert(xSet);
+ m_bCurrentRecordModified = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED));
+ m_bCurrentRecordNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
+
+ startFormListening( xSet, sal_False );
+
+ // set the locks for the current controls
+ if (getContainer().is())
+ {
+ m_aLoadEvent.Call();
+ }
+ }
+ else
+ {
+ m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
+ m_bCurrentRecordModified = sal_False;
+ m_bCurrentRecordNew = sal_False;
+ m_bLocked = sal_False;
+ }
+ m_bDBConnection = sal_True;
+ }
+ else
+ {
+ m_bDBConnection = sal_False;
+ m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
+ m_bCurrentRecordModified = sal_False;
+ m_bCurrentRecordNew = sal_False;
+ m_bLocked = sal_False;
+ }
+
+ Reference< XColumnsSupplier > xFormColumns( xForm, UNO_QUERY );
+ m_pColumnInfoCache.reset( xFormColumns.is() ? new ColumnInfoCache( xFormColumns ) : NULL );
+
+ updateAllDispatchers();
+}
+
+//------------------------------------------------------------------------------
+void FormController::updateAllDispatchers() const
+{
+ ::std::for_each(
+ m_aFeatureDispatchers.begin(),
+ m_aFeatureDispatchers.end(),
+ ::std::compose1(
+ UpdateAllListeners(),
+ ::std::select2nd< DispatcherContainer::value_type >()
+ )
+ );
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK(FormController, OnLoad, void*, EMPTYARG)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ m_bLocked = determineLockState();
+
+ setLocks();
+
+ if (!m_bLocked)
+ startListening();
+
+ // just one exception toggle the auto values
+ if (m_bCurrentRecordNew)
+ toggleAutoFields(sal_True);
+
+ return 1L;
+}
+
+//------------------------------------------------------------------------------
+void FormController::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ updateAllDispatchers();
+}
+
+//------------------------------------------------------------------------------
+void FormController::reloading(const EventObject& /*aEvent*/) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ // do the same like in unloading
+ // just one exception toggle the auto values
+ m_aToggleEvent.CancelPendingCall();
+ unload();
+}
+
+//------------------------------------------------------------------------------
+void FormController::reloaded(const EventObject& aEvent) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ loaded(aEvent);
+}
+
+//------------------------------------------------------------------------------
+void FormController::unloading(const EventObject& /*aEvent*/) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ unload();
+}
+
+//------------------------------------------------------------------------------
+void FormController::unload() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aLoadEvent.CancelPendingCall();
+
+ // be sure not to have autofields
+ if (m_bCurrentRecordNew)
+ toggleAutoFields(sal_False);
+
+ // remove bound field listing again
+ removeBoundFieldListener();
+
+ if (m_bDBConnection && isListeningForChanges())
+ stopListening();
+
+ Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
+ if ( m_bDBConnection && xSet.is() )
+ stopFormListening( xSet, sal_False );
+
+ m_bDBConnection = sal_False;
+ m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
+ m_bCurrentRecordModified = m_bCurrentRecordNew = m_bLocked = sal_False;
+
+ m_pColumnInfoCache.reset( NULL );
+}
+
+// -----------------------------------------------------------------------------
+void FormController::removeBoundFieldListener()
+{
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
+ while ( pControls != pControlsEnd )
+ {
+ Reference< XPropertySet > xProp( *pControls++, UNO_QUERY );
+ if ( xProp.is() )
+ xProp->removePropertyChangeListener( FM_PROP_BOUNDFIELD, this );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::startFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
+{
+ try
+ {
+ if ( m_bCanInsert || m_bCanUpdate ) // form can be modified
+ {
+ _rxForm->addPropertyChangeListener( FM_PROP_ISNEW, this );
+ _rxForm->addPropertyChangeListener( FM_PROP_ISMODIFIED, this );
+
+ if ( !_bPropertiesOnly )
+ {
+ // set the Listener for UI interaction
+ Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
+ if ( xApprove.is() )
+ xApprove->addRowSetApproveListener( this );
+
+ // listener for row set changes
+ Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
+ if ( xRowSet.is() )
+ xRowSet->addRowSetListener( this );
+ }
+ }
+
+ Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
+ if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
+ _rxForm->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::stopFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
+{
+ try
+ {
+ if ( m_bCanInsert || m_bCanUpdate )
+ {
+ _rxForm->removePropertyChangeListener( FM_PROP_ISNEW, this );
+ _rxForm->removePropertyChangeListener( FM_PROP_ISMODIFIED, this );
+
+ if ( !_bPropertiesOnly )
+ {
+ Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
+ if (xApprove.is())
+ xApprove->removeRowSetApproveListener(this);
+
+ Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
+ if ( xRowSet.is() )
+ xRowSet->removeRowSetListener( this );
+ }
+ }
+
+ Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
+ if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
+ _rxForm->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+// com::sun::star::sdbc::XRowSetListener
+//------------------------------------------------------------------------------
+void FormController::cursorMoved(const EventObject& /*event*/) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ // toggle the locking ?
+ if (m_bLocked != determineLockState())
+ {
+ m_bLocked = !m_bLocked;
+ setLocks();
+ if (isListeningForChanges())
+ startListening();
+ else
+ stopListening();
+ }
+
+ // neither the current control nor the current record are modified anymore
+ m_bCurrentRecordModified = m_bModified = sal_False;
+}
+
+//------------------------------------------------------------------------------
+void FormController::rowChanged(const EventObject& /*event*/) throw( RuntimeException )
+{
+ // not interested in ...
+}
+//------------------------------------------------------------------------------
+void FormController::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException )
+{
+ // not interested in ...
+}
+
+
+// XContainerListener
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::elementInserted(const ContainerEvent& evt) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ Reference< XControl > xControl( evt.Element, UNO_QUERY );
+ if ( !xControl.is() )
+ return;
+
+ Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
+ if (xModel.is() && m_xModelAsIndex == xModel->getParent())
+ {
+ insertControl(xControl);
+
+ if ( m_aTabActivationTimer.IsActive() )
+ m_aTabActivationTimer.Stop();
+
+ m_aTabActivationTimer.Start();
+ }
+ // are we in filtermode and a XModeSelector has inserted an element
+ else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
+ {
+ xModel = Reference< XFormComponent > (evt.Source, UNO_QUERY);
+ if (xModel.is() && m_xModelAsIndex == xModel->getParent())
+ {
+ Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // does the model use a bound field ?
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+
+ Reference< XTextComponent > xText(xControl, UNO_QUERY);
+ // may we filter the field?
+ if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
+ ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
+ {
+ m_aFilterComponents.push_back( xText );
+ xText->addTextListener( this );
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::elementReplaced(const ContainerEvent& evt) throw( RuntimeException )
+{
+ // simulate an elementRemoved
+ ContainerEvent aRemoveEvent( evt );
+ aRemoveEvent.Element = evt.ReplacedElement;
+ aRemoveEvent.ReplacedElement = Any();
+ elementRemoved( aRemoveEvent );
+
+ // simulate an elementInserted
+ ContainerEvent aInsertEvent( evt );
+ aInsertEvent.ReplacedElement = Any();
+ elementInserted( aInsertEvent );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::elementRemoved(const ContainerEvent& evt) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ Reference< XControl > xControl;
+ evt.Element >>= xControl;
+ if (!xControl.is())
+ return;
+
+ Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
+ if (xModel.is() && m_xModelAsIndex == xModel->getParent())
+ {
+ removeControl(xControl);
+ // TabOrder nicht neu berechnen, da das intern schon funktionieren muß!
+ }
+ // are we in filtermode and a XModeSelector has inserted an element
+ else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
+ {
+ FilterComponents::iterator componentPos = ::std::find(
+ m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
+ if ( componentPos != m_aFilterComponents.end() )
+ m_aFilterComponents.erase( componentPos );
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XControl > FormController::isInList(const Reference< XWindowPeer > & xPeer) const
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ const Reference< XControl >* pControls = m_aControls.getConstArray();
+
+ sal_uInt32 nCtrls = m_aControls.getLength();
+ for ( sal_uInt32 n = 0; n < nCtrls && xPeer.is(); ++n, ++pControls )
+ {
+ if ( pControls->is() )
+ {
+ Reference< XVclWindowPeer > xCtrlPeer( (*pControls)->getPeer(), UNO_QUERY);
+ if ( ( xCtrlPeer.get() == xPeer.get() ) || xCtrlPeer->isChild( xPeer ) )
+ return *pControls;
+ }
+ }
+ return Reference< XControl > ();
+}
+
+//------------------------------------------------------------------------------
+void FormController::activateFirst() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::activateFirst : invalid aggregate !");
+ if (m_xTabController.is())
+ m_xTabController->activateFirst();
+}
+
+//------------------------------------------------------------------------------
+void FormController::activateLast() throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ DBG_ASSERT(m_xTabController.is(), "FormController::activateLast : invalid aggregate !");
+ if (m_xTabController.is())
+ m_xTabController->activateLast();
+}
+
+// XFormController
+//------------------------------------------------------------------------------
+Reference< XFormOperations > SAL_CALL FormController::getFormOperations() throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ return m_xFormOperations;
+}
+
+//------------------------------------------------------------------------------
+Reference< XControl> SAL_CALL FormController::getCurrentControl(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ return m_xCurrentControl;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_aActivateListeners.addInterface(l);
+}
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeActivateListener(const Reference< XFormControllerListener > & l) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_aActivateListeners.removeInterface(l);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addChildController( const Reference< XFormController >& _ChildController ) throw( RuntimeException, IllegalArgumentException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if ( !_ChildController.is() )
+ throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
+ // TODO: (localized) error message
+
+ // the parent of our (to-be-)child must be our own model
+ Reference< XFormComponent > xFormOfChild( _ChildController->getModel(), UNO_QUERY );
+ if ( !xFormOfChild.is() )
+ throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
+ // TODO: (localized) error message
+
+ if ( xFormOfChild->getParent() != m_xModelAsIndex )
+ throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
+ // TODO: (localized) error message
+
+ m_aChilds.push_back( _ChildController );
+ _ChildController->setParent( *this );
+
+ // search the position of the model within the form
+ sal_uInt32 nPos = m_xModelAsIndex->getCount();
+ Reference< XFormComponent > xTemp;
+ for( ; nPos; )
+ {
+ m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
+ if ( xFormOfChild == xTemp )
+ {
+ Reference< XInterface > xIfc( _ChildController, UNO_QUERY );
+ m_xModelAsManager->attach( nPos, xIfc, makeAny( _ChildController) );
+ break;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+Reference< XFormControllerContext > SAL_CALL FormController::getContext() throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ return m_xContext;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::setContext( const Reference< XFormControllerContext >& _context ) throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_xContext = _context;
+}
+
+//------------------------------------------------------------------------------
+Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler() throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ return m_xInteractionHandler;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::setInteractionHandler( const Reference< XInteractionHandler >& _interactionHandler ) throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+ m_xInteractionHandler = _interactionHandler;
+}
+
+//------------------------------------------------------------------------------
+void FormController::setFilter(::std::vector<FmFieldInfo>& rFieldInfos)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ // create the composer
+ Reference< XRowSet > xForm(m_xModelAsIndex, UNO_QUERY);
+ Reference< XConnection > xConnection(OStaticDataAccessTools().getRowSetConnection(xForm));
+ if (xForm.is())
+ {
+ try
+ {
+ Reference< XMultiServiceFactory > xFactory( xConnection, UNO_QUERY_THROW );
+ m_xComposer.set(
+ xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ),
+ UNO_QUERY_THROW );
+
+ Reference< XPropertySet > xSet( xForm, UNO_QUERY );
+ ::rtl::OUString sStatement = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_ACTIVECOMMAND ) );
+ ::rtl::OUString sFilter = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_FILTER ) );
+ m_xComposer->setElementaryQuery( sStatement );
+ m_xComposer->setFilter( sFilter );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ if (m_xComposer.is())
+ {
+ Sequence < PropertyValue> aLevel;
+ Sequence< Sequence < PropertyValue > > aFilterRows = m_xComposer->getStructuredFilter();
+
+ // ok, we recieve the list of filters as sequence of fieldnames, value
+ // now we have to transform the fieldname into UI names, that could be a label of the field or
+ // a aliasname or the fieldname itself
+
+ // first adjust the field names if necessary
+ Reference< XNameAccess > xQueryColumns =
+ Reference< XColumnsSupplier >( m_xComposer, UNO_QUERY_THROW )->getColumns();
+
+ for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
+ iter != rFieldInfos.end(); iter++)
+ {
+ if ( xQueryColumns->hasByName((*iter).aFieldName) )
+ {
+ if ( (xQueryColumns->getByName((*iter).aFieldName) >>= (*iter).xField) && (*iter).xField.is() )
+ (*iter).xField->getPropertyValue(FM_PROP_REALNAME) >>= (*iter).aFieldName;
+ }
+ }
+
+ Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
+ // now transfer the filters into Value/TextComponent pairs
+ ::comphelper::UStringMixEqual aCompare(xMetaData->storesMixedCaseQuotedIdentifiers());
+
+ // need to parse criteria localized
+ OStaticDataAccessTools aStaticTools;
+ Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats(xConnection, sal_True));
+ Reference< XNumberFormatter> xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY );
+ xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
+ Locale aAppLocale = Application::GetSettings().GetUILocale();
+ LocaleDataWrapper aLocaleWrapper( m_aContext.getLegacyServiceFactory(), aAppLocale );
+
+ // retrieving the filter
+ const Sequence < PropertyValue >* pRow = aFilterRows.getConstArray();
+ for (sal_Int32 i = 0, nLen = aFilterRows.getLength(); i < nLen; ++i)
+ {
+ FmFilterRow aRow;
+
+ // search a field for the given name
+ const PropertyValue* pRefValues = pRow[i].getConstArray();
+ for (sal_Int32 j = 0, nLen1 = pRow[i].getLength(); j < nLen1; j++)
+ {
+ // look for the text component
+ Reference< XPropertySet > xField;
+ try
+ {
+ Reference< XPropertySet > xSet;
+ ::rtl::OUString aRealName;
+
+ // first look with the given name
+ if (xQueryColumns->hasByName(pRefValues[j].Name))
+ {
+ xQueryColumns->getByName(pRefValues[j].Name) >>= xSet;
+
+ // get the RealName
+ xSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RealName"))) >>= aRealName;
+
+ // compare the condition field name and the RealName
+ if (aCompare(aRealName, pRefValues[j].Name))
+ xField = xSet;
+ }
+ if (!xField.is())
+ {
+ // no we have to check every column to find the realname
+ Reference< XIndexAccess > xColumnsByIndex(xQueryColumns, UNO_QUERY);
+ for (sal_Int32 n = 0, nCount = xColumnsByIndex->getCount(); n < nCount; n++)
+ {
+ xColumnsByIndex->getByIndex(n) >>= xSet;
+ xSet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RealName"))) >>= aRealName;
+ if (aCompare(aRealName, pRefValues[j].Name))
+ {
+ // get the column by its alias
+ xField = xSet;
+ break;
+ }
+ }
+ }
+ if (!xField.is())
+ continue;
+ }
+ catch (const Exception&)
+ {
+ continue;
+ }
+
+ // find the text component
+ for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
+ iter != rFieldInfos.end(); iter++)
+ {
+ // we found the field so insert a new entry to the filter row
+ if ((*iter).xField == xField)
+ {
+ // do we already have the control ?
+ if (aRow.find((*iter).xText) != aRow.end())
+ {
+ ::rtl::OUString aCompText = aRow[(*iter).xText];
+ aCompText += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
+ ::rtl::OString aVal = m_xParser->getContext().getIntlKeywordAscii(OParseContext::KEY_AND);
+ aCompText += ::rtl::OUString(aVal.getStr(),aVal.getLength(),RTL_TEXTENCODING_ASCII_US);
+ aCompText += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
+ aCompText += ::comphelper::getString(pRefValues[j].Value);
+ aRow[(*iter).xText] = aCompText;
+ }
+ else
+ {
+ ::rtl::OUString sPredicate,sErrorMsg;
+ pRefValues[j].Value >>= sPredicate;
+ ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree(sErrorMsg, sPredicate, xFormatter, xField);
+ if ( xParseNode.is() )
+ {
+ ::rtl::OUString sCriteria;
+ xParseNode->parseNodeToPredicateStr( sCriteria
+ ,xConnection
+ ,xFormatter
+ ,xField
+ ,aAppLocale
+ ,(sal_Char)aLocaleWrapper.getNumDecimalSep().GetChar(0)
+ ,getParseContext());
+ aRow[(*iter).xText] = sCriteria;
+ }
+ }
+ }
+ }
+ }
+
+ if (aRow.empty())
+ continue;
+
+ impl_addFilterRow( aRow );
+ }
+ }
+
+ // now set the filter controls
+ for ( ::std::vector<FmFieldInfo>::iterator field = rFieldInfos.begin();
+ field != rFieldInfos.end();
+ ++field
+ )
+ {
+ m_aFilterComponents.push_back( field->xText );
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormController::startFiltering()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+
+ OStaticDataAccessTools aStaticTools;
+ Reference< XConnection > xConnection( aStaticTools.getRowSetConnection( Reference< XRowSet >( m_xModelAsIndex, UNO_QUERY ) ) );
+ if ( !xConnection.is() )
+ // nothing to do - can't filter a form which is not connected
+ // 98023 - 19.03.2002 - fs@openoffice.org
+ return;
+
+ // stop listening for controls
+ if (isListeningForChanges())
+ stopListening();
+
+ m_bFiltering = sal_True;
+
+ // as we don't want new controls to be attached to the scripting environment
+ // we change attach flags
+ m_bAttachEvents = sal_False;
+
+ // Austauschen der Kontrols fuer das aktuelle Formular
+ Sequence< Reference< XControl > > aControlsCopy( m_aControls );
+ const Reference< XControl >* pControls = aControlsCopy.getConstArray();
+ sal_Int32 nControlCount = aControlsCopy.getLength();
+
+ // the control we have to activate after replacement
+ Reference< XDatabaseMetaData > xMetaData(xConnection->getMetaData());
+ Reference< XNumberFormatsSupplier > xFormatSupplier = aStaticTools.getNumberFormats(xConnection, sal_True);
+ Reference< XNumberFormatter > xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY );
+ xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
+
+ // structure for storing the field info
+ ::std::vector<FmFieldInfo> aFieldInfos;
+
+ for (sal_Int32 i = nControlCount; i > 0;)
+ {
+ Reference< XControl > xControl = pControls[--i];
+ if (xControl.is())
+ {
+ // no events for the control anymore
+ removeFromEventAttacher(xControl);
+
+ // do we have a mode selector
+ Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
+ if (xSelector.is())
+ {
+ xSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ) );
+
+ // listening for new controls of the selector
+ Reference< XContainer > xContainer(xSelector, UNO_QUERY);
+ if (xContainer.is())
+ xContainer->addContainerListener(this);
+
+ Reference< XEnumerationAccess > xElementAccess(xSelector, UNO_QUERY);
+ if (xElementAccess.is())
+ {
+ Reference< XEnumeration > xEnumeration(xElementAccess->createEnumeration());
+ Reference< XControl > xSubControl;
+ while (xEnumeration->hasMoreElements())
+ {
+ xEnumeration->nextElement() >>= xSubControl;
+ if (xSubControl.is())
+ {
+ Reference< XPropertySet > xSet(xSubControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // does the model use a bound field ?
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+
+ Reference< XTextComponent > xText(xSubControl, UNO_QUERY);
+ // may we filter the field?
+ if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
+ ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
+ {
+ aFieldInfos.push_back(FmFieldInfo(xField, xText));
+ xText->addTextListener(this);
+ }
+ }
+ }
+ }
+ }
+ continue;
+ }
+
+ Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY );
+ if (xModel.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xModel))
+ {
+ // does the model use a bound field ?
+ Any aVal = xModel->getPropertyValue(FM_PROP_BOUNDFIELD);
+ Reference< XPropertySet > xField;
+ aVal >>= xField;
+
+ // may we filter the field?
+
+ if ( xField.is()
+ && ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
+ && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
+ )
+ {
+ // create a filter control
+ Sequence< Any > aCreationArgs( 3 );
+ aCreationArgs[ 0 ] <<= NamedValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MessageParent")), makeAny( VCLUnoHelper::GetInterface( getDialogParentWindow() ) ) );
+ aCreationArgs[ 1 ] <<= NamedValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormatter")), makeAny( xFormatter ) );
+ aCreationArgs[ 2 ] <<= NamedValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ControlModel")), makeAny( xModel ) );
+ Reference< XControl > xFilterControl(
+ m_aContext.createComponentWithArguments( "com.sun.star.form.control.FilterControl", aCreationArgs ),
+ UNO_QUERY
+ );
+ DBG_ASSERT( xFilterControl.is(), "FormController::startFiltering: could not create a filter control!" );
+
+ if ( replaceControl( xControl, xFilterControl ) )
+ {
+ Reference< XTextComponent > xFilterText( xFilterControl, UNO_QUERY );
+ aFieldInfos.push_back( FmFieldInfo( xField, xFilterText ) );
+ xFilterText->addTextListener(this);
+ }
+ }
+ }
+ else
+ {
+ // abmelden vom EventManager
+ }
+ }
+ }
+
+ // we have all filter controls now, so the next step is to read the filters from the form
+ // resolve all aliases and set the current filter to the according structure
+ setFilter(aFieldInfos);
+
+ Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
+ if ( xSet.is() )
+ stopFormListening( xSet, sal_True );
+
+ impl_setTextOnAllFilter_throw();
+
+ // lock all controls which are not used for filtering
+ m_bLocked = determineLockState();
+ setLocks();
+ m_bAttachEvents = sal_True;
+}
+
+//------------------------------------------------------------------------------
+void FormController::stopFiltering()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ if ( !m_bFiltering ) // #104693# OJ
+ { // nothing to do
+ return;
+ }
+
+ m_bFiltering = sal_False;
+ m_bDetachEvents = sal_False;
+
+ ::comphelper::disposeComponent(m_xComposer);
+
+ // Austauschen der Kontrols fuer das aktuelle Formular
+ Sequence< Reference< XControl > > aControlsCopy( m_aControls );
+ const Reference< XControl > * pControls = aControlsCopy.getConstArray();
+ sal_Int32 nControlCount = aControlsCopy.getLength();
+
+ // clear the filter control map
+ ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
+ m_aFilterComponents.clear();
+
+ for ( sal_Int32 i = nControlCount; i > 0; )
+ {
+ Reference< XControl > xControl = pControls[--i];
+ if (xControl.is())
+ {
+ // now enable eventhandling again
+ addToEventAttacher(xControl);
+
+ Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
+ if (xSelector.is())
+ {
+ xSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) );
+
+ // listening for new controls of the selector
+ Reference< XContainer > xContainer(xSelector, UNO_QUERY);
+ if (xContainer.is())
+ xContainer->removeContainerListener(this);
+ continue;
+ }
+
+ Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
+ if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
+ {
+ // does the model use a bound field ?
+ Reference< XPropertySet > xField;
+ xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
+
+ // may we filter the field?
+ if ( xField.is()
+ && ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
+ && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
+ )
+ {
+ ::rtl::OUString sServiceName;
+ OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
+ Reference< XControl > xNewControl( m_aContext.createComponent( sServiceName ), UNO_QUERY );
+ replaceControl( xControl, xNewControl );
+ }
+ }
+ }
+ }
+
+ Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
+ if ( xSet.is() )
+ startFormListening( xSet, sal_True );
+
+ m_bDetachEvents = sal_True;
+
+ m_aFilterRows.clear();
+ m_nCurrentFilterPosition = -1;
+
+ // release the locks if possible
+ // lock all controls which are not used for filtering
+ m_bLocked = determineLockState();
+ setLocks();
+
+ // restart listening for control modifications
+ if (isListeningForChanges())
+ startListening();
+}
+
+// XModeSelector
+//------------------------------------------------------------------------------
+void FormController::setMode(const ::rtl::OUString& Mode) throw( NoSupportException, RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ if (!supportsMode(Mode))
+ throw NoSupportException();
+
+ if (Mode == m_aMode)
+ return;
+
+ m_aMode = Mode;
+
+ if ( Mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FilterMode" ) ) )
+ startFiltering();
+ else
+ stopFiltering();
+
+ for (FmFormControllers::const_iterator i = m_aChilds.begin();
+ i != m_aChilds.end(); ++i)
+ {
+ Reference< XModeSelector > xMode(*i, UNO_QUERY);
+ if ( xMode.is() )
+ xMode->setMode(Mode);
+ }
+}
+
+//------------------------------------------------------------------------------
+::rtl::OUString SAL_CALL FormController::getMode(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ return m_aMode;
+}
+
+//------------------------------------------------------------------------------
+Sequence< ::rtl::OUString > SAL_CALL FormController::getSupportedModes(void) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ static Sequence< ::rtl::OUString > aModes;
+ if (!aModes.getLength())
+ {
+ aModes.realloc(2);
+ ::rtl::OUString* pModes = aModes.getArray();
+ pModes[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) );
+ pModes[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) );
+ }
+ return aModes;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::supportsMode(const ::rtl::OUString& Mode) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ Sequence< ::rtl::OUString > aModes(getSupportedModes());
+ const ::rtl::OUString* pModes = aModes.getConstArray();
+ for (sal_Int32 i = aModes.getLength(); i > 0; )
+ {
+ if (pModes[--i] == Mode)
+ return sal_True;
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+Window* FormController::getDialogParentWindow()
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ Window* pParentWindow = NULL;
+ try
+ {
+ Reference< XControl > xContainerControl( getContainer(), UNO_QUERY_THROW );
+ Reference< XWindowPeer > xContainerPeer( xContainerControl->getPeer(), UNO_QUERY_THROW );
+ pParentWindow = VCLUnoHelper::GetWindow( xContainerPeer );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return pParentWindow;
+}
+//------------------------------------------------------------------------------
+bool FormController::checkFormComponentValidity( ::rtl::OUString& /* [out] */ _rFirstInvalidityExplanation, Reference< XControlModel >& /* [out] */ _rxFirstInvalidModel ) SAL_THROW(())
+{
+ try
+ {
+ Reference< XEnumerationAccess > xControlEnumAcc( getModel(), UNO_QUERY );
+ Reference< XEnumeration > xControlEnumeration;
+ if ( xControlEnumAcc.is() )
+ xControlEnumeration = xControlEnumAcc->createEnumeration();
+ OSL_ENSURE( xControlEnumeration.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
+ if ( !xControlEnumeration.is() )
+ // assume all valid
+ return true;
+
+ Reference< XValidatableFormComponent > xValidatable;
+ while ( xControlEnumeration->hasMoreElements() )
+ {
+ if ( !( xControlEnumeration->nextElement() >>= xValidatable ) )
+ // control does not support validation
+ continue;
+
+ if ( xValidatable->isValid() )
+ continue;
+
+ Reference< XValidator > xValidator( xValidatable->getValidator() );
+ OSL_ENSURE( xValidator.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
+ if ( !xValidator.is() )
+ // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
+ continue;
+
+ _rFirstInvalidityExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
+ _rxFirstInvalidModel = _rxFirstInvalidModel.query( xValidatable );
+ return false;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------------
+Reference< XControl > FormController::locateControl( const Reference< XControlModel >& _rxModel ) SAL_THROW(())
+{
+ try
+ {
+ Sequence< Reference< XControl > > aControls( getControls() );
+ const Reference< XControl >* pControls = aControls.getConstArray();
+ const Reference< XControl >* pControlsEnd = aControls.getConstArray() + aControls.getLength();
+
+ for ( ; pControls != pControlsEnd; ++pControls )
+ {
+ OSL_ENSURE( pControls->is(), "FormController::locateControl: NULL-control?" );
+ if ( pControls->is() )
+ {
+ if ( ( *pControls)->getModel() == _rxModel )
+ return *pControls;
+ }
+ }
+ OSL_ENSURE( sal_False, "FormController::locateControl: did not find a control for this model!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return NULL;
+}
+
+//------------------------------------------------------------------------------
+namespace
+{
+ void displayErrorSetFocus( const String& _rMessage, const Reference< XControl >& _rxFocusControl, Window* _pDialogParent )
+ {
+ SQLContext aError;
+ aError.Message = String( SVX_RES( RID_STR_WRITEERROR ) );
+ aError.Details = _rMessage;
+ displayException( aError, _pDialogParent );
+
+ if ( _rxFocusControl.is() )
+ {
+ Reference< XWindow > xControlWindow( _rxFocusControl, UNO_QUERY );
+ OSL_ENSURE( xControlWindow.is(), "displayErrorSetFocus: invalid control!" );
+ if ( xControlWindow.is() )
+ xControlWindow->setFocus();
+ }
+ }
+
+ sal_Bool lcl_shouldValidateRequiredFields_nothrow( const Reference< XInterface >& _rxForm )
+ {
+ try
+ {
+ static ::rtl::OUString s_sFormsCheckRequiredFields( RTL_CONSTASCII_USTRINGPARAM( "FormsCheckRequiredFields" ) );
+
+ // first, check whether the form has a property telling us the answer
+ // this allows people to use the XPropertyContainer interface of a form to control
+ // the behaviour on a per-form basis.
+ Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPSI( xFormProps->getPropertySetInfo() );
+ if ( xPSI->hasPropertyByName( s_sFormsCheckRequiredFields ) )
+ {
+ sal_Bool bShouldValidate = true;
+ OSL_VERIFY( xFormProps->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
+ return bShouldValidate;
+ }
+
+ // next, check the data source which created the connection
+ Reference< XChild > xConnectionAsChild( xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ), UNO_QUERY_THROW );
+ Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY );
+ if ( !xDataSource.is() )
+ // seldom (but possible): this is not a connection created by a data source
+ return sal_True;
+
+ Reference< XPropertySet > xDataSourceSettings(
+ xDataSource->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ),
+ UNO_QUERY_THROW );
+
+ sal_Bool bShouldValidate = true;
+ OSL_VERIFY( xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
+ return bShouldValidate;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return sal_True;
+ }
+}
+
+// XRowSetApproveListener
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::approveRowChange(const RowChangeEvent& _rEvent) throw( RuntimeException )
+{
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
+ sal_Bool bValid = sal_True;
+ if (aIter.hasMoreElements())
+ {
+ RowChangeEvent aEvt( _rEvent );
+ aEvt.Source = *this;
+ bValid = ((XRowSetApproveListener*)aIter.next())->approveRowChange(aEvt);
+ }
+
+ if ( !bValid )
+ return bValid;
+
+ if ( ( _rEvent.Action != RowChangeAction::INSERT )
+ && ( _rEvent.Action != RowChangeAction::UPDATE )
+ )
+ return bValid;
+
+ // if some of the control models are bound to validators, check them
+ ::rtl::OUString sInvalidityExplanation;
+ Reference< XControlModel > xInvalidModel;
+ if ( !checkFormComponentValidity( sInvalidityExplanation, xInvalidModel ) )
+ {
+ Reference< XControl > xControl( locateControl( xInvalidModel ) );
+ aGuard.clear();
+ displayErrorSetFocus( sInvalidityExplanation, xControl, getDialogParentWindow() );
+ return false;
+ }
+
+ // check values on NULL and required flag
+ if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent.Source ) )
+ return sal_True;
+
+ OSL_ENSURE( m_pColumnInfoCache.get(), "FormController::approveRowChange: no column infos!" );
+ if ( !m_pColumnInfoCache.get() )
+ return sal_True;
+
+ try
+ {
+ if ( !m_pColumnInfoCache->controlsInitialized() )
+ m_pColumnInfoCache->initializeControls( getControls() );
+
+ size_t colCount = m_pColumnInfoCache->getColumnCount();
+ for ( size_t col = 0; col < colCount; ++col )
+ {
+ const ColumnInfo& rColInfo = m_pColumnInfoCache->getColumnInfo( col );
+ if ( rColInfo.nNullable != ColumnValue::NO_NULLS )
+ continue;
+
+ if ( rColInfo.bAutoIncrement )
+ continue;
+
+ if ( rColInfo.bReadOnly )
+ continue;
+
+ if ( !rColInfo.xFirstControlWithInputRequired.is() && !rColInfo.xFirstGridWithInputRequiredColumn.is() )
+ continue;
+
+ // TODO: in case of binary fields, this "getString" below is extremely expensive
+ if ( rColInfo.xColumn->getString().getLength() || !rColInfo.xColumn->wasNull() )
+ continue;
+
+ String sMessage( SVX_RES( RID_ERR_FIELDREQUIRED ) );
+ sMessage.SearchAndReplace( '#', rColInfo.sName );
+
+ // the control to focus
+ Reference< XControl > xControl( rColInfo.xFirstControlWithInputRequired );
+ if ( !xControl.is() )
+ xControl.set( rColInfo.xFirstGridWithInputRequiredColumn, UNO_QUERY );
+
+ aGuard.clear();
+ displayErrorSetFocus( sMessage, rColInfo.xFirstControlWithInputRequired, getDialogParentWindow() );
+ return sal_False;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::approveCursorMove(const EventObject& event) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
+ if (aIter.hasMoreElements())
+ {
+ EventObject aEvt(event);
+ aEvt.Source = *this;
+ return ((XRowSetApproveListener*)aIter.next())->approveCursorMove(aEvt);
+ }
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::approveRowSetChange(const EventObject& event) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
+ if (aIter.hasMoreElements())
+ {
+ EventObject aEvt(event);
+ aEvt.Source = *this;
+ return ((XRowSetApproveListener*)aIter.next())->approveRowSetChange(aEvt);
+ }
+
+ return sal_True;
+}
+
+// XRowSetApproveBroadcaster
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aRowSetApproveListeners.addInterface(_rxListener);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aRowSetApproveListeners.removeInterface(_rxListener);
+}
+
+// XErrorListener
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::errorOccured(const SQLErrorEvent& aEvent) throw( RuntimeException )
+{
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aErrorListeners);
+ if (aIter.hasMoreElements())
+ {
+ SQLErrorEvent aEvt(aEvent);
+ aEvt.Source = *this;
+ ((XSQLErrorListener*)aIter.next())->errorOccured(aEvt);
+ }
+ else
+ {
+ aGuard.clear();
+ displayException( aEvent );
+ }
+}
+
+// XErrorBroadcaster
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aErrorListeners.addInterface(aListener);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeSQLErrorListener(const Reference< XSQLErrorListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aErrorListeners.removeInterface(aListener);
+}
+
+// XDatabaseParameterBroadcaster2
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aParameterListeners.addInterface(aListener);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aParameterListeners.removeInterface(aListener);
+}
+
+// XDatabaseParameterBroadcaster
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
+{
+ FormController::addDatabaseParameterListener( aListener );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener) throw( RuntimeException )
+{
+ FormController::removeDatabaseParameterListener( aListener );
+}
+
+// XDatabaseParameterListener
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::approveParameter(const DatabaseParameterEvent& aEvent) throw( RuntimeException )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aParameterListeners);
+ if (aIter.hasMoreElements())
+ {
+ DatabaseParameterEvent aEvt(aEvent);
+ aEvt.Source = *this;
+ return ((XDatabaseParameterListener*)aIter.next())->approveParameter(aEvt);
+ }
+ else
+ {
+ // default handling: instantiate an interaction handler and let it handle the parameter request
+ try
+ {
+ if ( !ensureInteractionHandler() )
+ return sal_False;
+
+ // two continuations allowed: OK and Cancel
+ OParameterContinuation* pParamValues = new OParameterContinuation;
+ OInteractionAbort* pAbort = new OInteractionAbort;
+ // the request
+ ParametersRequest aRequest;
+ aRequest.Parameters = aEvent.Parameters;
+ aRequest.Connection = OStaticDataAccessTools().getRowSetConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
+ OInteractionRequest* pParamRequest = new OInteractionRequest(makeAny(aRequest));
+ Reference< XInteractionRequest > xParamRequest(pParamRequest);
+ // some knittings
+ pParamRequest->addContinuation(pParamValues);
+ pParamRequest->addContinuation(pAbort);
+
+ // handle the request
+ m_xInteractionHandler->handle(xParamRequest);
+
+ if (!pParamValues->wasSelected())
+ // canceled
+ return sal_False;
+
+ // transfer the values into the parameter supplier
+ Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
+ if (aFinalValues.getLength() != aRequest.Parameters->getCount())
+ {
+ DBG_ERROR("FormController::approveParameter: the InteractionHandler returned nonsense!");
+ return sal_False;
+ }
+ const PropertyValue* pFinalValues = aFinalValues.getConstArray();
+ for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
+ {
+ Reference< XPropertySet > xParam;
+ ::cppu::extractInterface(xParam, aRequest.Parameters->getByIndex(i));
+ if (xParam.is())
+ {
+#ifdef DBG_UTIL
+ ::rtl::OUString sName;
+ xParam->getPropertyValue(FM_PROP_NAME) >>= sName;
+ DBG_ASSERT(sName.equals(pFinalValues->Name), "FormController::approveParameter: suspicious value names!");
+#endif
+ try { xParam->setPropertyValue(FM_PROP_VALUE, pFinalValues->Value); }
+ catch(Exception&)
+ {
+ DBG_ERROR("FormController::approveParameter: setting one of the properties failed!");
+ }
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ return sal_True;
+}
+
+// XConfirmDeleteBroadcaster
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aDeleteListeners.addInterface(aListener);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ m_aDeleteListeners.removeInterface(aListener);
+}
+
+// XConfirmDeleteListener
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL FormController::confirmDelete(const RowChangeEvent& aEvent) throw( RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ impl_checkDisposed_throw();
+
+ ::cppu::OInterfaceIteratorHelper aIter(m_aDeleteListeners);
+ if (aIter.hasMoreElements())
+ {
+ RowChangeEvent aEvt(aEvent);
+ aEvt.Source = *this;
+ return ((XConfirmDeleteListener*)aIter.next())->confirmDelete(aEvt);
+ }
+ // default handling: instantiate an interaction handler and let it handle the request
+
+ String sTitle;
+ sal_Int32 nLength = aEvent.Rows;
+ if ( nLength > 1 )
+ {
+ sTitle = SVX_RES( RID_STR_DELETECONFIRM_RECORDS );
+ sTitle.SearchAndReplace( '#', String::CreateFromInt32( nLength ) );
+ }
+ else
+ sTitle = SVX_RES( RID_STR_DELETECONFIRM_RECORD );
+
+ try
+ {
+ if ( !ensureInteractionHandler() )
+ return sal_False;
+
+ // two continuations allowed: Yes and No
+ OInteractionApprove* pApprove = new OInteractionApprove;
+ OInteractionDisapprove* pDisapprove = new OInteractionDisapprove;
+
+ // the request
+ SQLWarning aWarning;
+ aWarning.Message = sTitle;
+ SQLWarning aDetails;
+ aDetails.Message = String( SVX_RES( RID_STR_DELETECONFIRM ) );
+ aWarning.NextException <<= aDetails;
+
+ OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aWarning ) );
+ Reference< XInteractionRequest > xRequest( pRequest );
+
+ // some knittings
+ pRequest->addContinuation( pApprove );
+ pRequest->addContinuation( pDisapprove );
+
+ // handle the request
+ m_xInteractionHandler->handle( xRequest );
+
+ if ( pApprove->wasSelected() )
+ return sal_True;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // for now, just copy the ids of the features, because ....
+ ::std::copy( _Features.getConstArray(), _Features.getConstArray() + _Features.getLength(),
+ ::std::insert_iterator< ::std::set< sal_Int16 > >( m_aInvalidFeatures, m_aInvalidFeatures.begin() )
+ );
+
+ // ... we will do the real invalidation asynchronously
+ if ( !m_aFeatureInvalidationTimer.IsActive() )
+ m_aFeatureInvalidationTimer.Start();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::invalidateAllFeatures( ) throw (RuntimeException)
+{
+ ::osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ Sequence< sal_Int16 > aInterceptedFeatures( m_aFeatureDispatchers.size() );
+ ::std::transform(
+ m_aFeatureDispatchers.begin(),
+ m_aFeatureDispatchers.end(),
+ aInterceptedFeatures.getArray(),
+ ::std::select1st< DispatcherContainer::value_type >()
+ );
+
+ aGuard.clear();
+ if ( aInterceptedFeatures.getLength() )
+ invalidateFeatures( aInterceptedFeatures );
+}
+
+//------------------------------------------------------------------------------
+Reference< XDispatch >
+FormController::interceptedQueryDispatch( const URL& aURL,
+ const ::rtl::OUString& /*aTargetFrameName*/, sal_Int32 /*nSearchFlags*/)
+ throw( RuntimeException )
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ Reference< XDispatch > xReturn;
+ // dispatches handled by ourself
+ if ( ( aURL.Complete == FMURL_CONFIRM_DELETION )
+ || ( ( aURL.Complete.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:/InteractionHandler" ) ) )
+ && ensureInteractionHandler()
+ )
+ )
+ xReturn = static_cast< XDispatch* >( this );
+
+ // dispatches of FormSlot-URLs we have to translate
+ if ( !xReturn.is() && m_xFormOperations.is() )
+ {
+ // find the slot id which corresponds to the URL
+ sal_Int32 nFeatureSlotId = ::svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL.Main );
+ sal_Int16 nFormFeature = ( nFeatureSlotId != -1 ) ? ::svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId ) : -1;
+ if ( nFormFeature > 0 )
+ {
+ // get the dispatcher for this feature, create if necessary
+ DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( nFormFeature );
+ if ( aDispatcherPos == m_aFeatureDispatchers.end() )
+ {
+ aDispatcherPos = m_aFeatureDispatchers.insert(
+ DispatcherContainer::value_type( nFormFeature, new ::svx::OSingleFeatureDispatcher( aURL, nFormFeature, m_xFormOperations, m_aMutex ) )
+ ).first;
+ }
+
+ OSL_ENSURE( aDispatcherPos->second.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
+ return aDispatcherPos->second;
+ }
+ }
+
+ // no more to offer
+ return xReturn;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArgs ) throw (RuntimeException)
+{
+ if ( _rArgs.getLength() != 1 )
+ {
+ DBG_ERROR( "FormController::dispatch: no arguments -> no dispatch!" );
+ return;
+ }
+
+ if ( _rURL.Complete.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:/InteractionHandler" ) ) )
+ {
+ Reference< XInteractionRequest > xRequest;
+ OSL_VERIFY( _rArgs[0].Value >>= xRequest );
+ if ( xRequest.is() )
+ handle( xRequest );
+ return;
+ }
+
+ if ( _rURL.Complete == FMURL_CONFIRM_DELETION )
+ {
+ DBG_ERROR( "FormController::dispatch: How do you expect me to return something via this call?" );
+ // confirmDelete has a return value - dispatch hasn't
+ return;
+ }
+
+ DBG_ERROR( "FormController::dispatch: unknown URL!" );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::addStatusListener( const Reference< XStatusListener >& _rxListener, const URL& _rURL ) throw (RuntimeException)
+{
+ if (_rURL.Complete == FMURL_CONFIRM_DELETION)
+ {
+ if (_rxListener.is())
+ { // send an initial statusChanged event
+ FeatureStateEvent aEvent;
+ aEvent.FeatureURL = _rURL;
+ aEvent.IsEnabled = sal_True;
+ _rxListener->statusChanged(aEvent);
+ // and don't add the listener at all (the status will never change)
+ }
+ }
+ else
+ OSL_ENSURE(sal_False, "FormController::addStatusListener: invalid (unsupported) URL!");
+}
+
+//------------------------------------------------------------------------------
+Reference< XInterface > SAL_CALL FormController::getParent() throw( RuntimeException )
+{
+ return m_xParent;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent) throw( NoSupportException, RuntimeException )
+{
+ m_xParent = Parent;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::removeStatusListener( const Reference< XStatusListener >& /*_rxListener*/, const URL& _rURL ) throw (RuntimeException)
+{
+ (void)_rURL;
+ OSL_ENSURE(_rURL.Complete == FMURL_CONFIRM_DELETION, "FormController::removeStatusListener: invalid (unsupported) URL!");
+ // we never really added the listener, so we don't need to remove it
+}
+
+//------------------------------------------------------------------------------
+Reference< XDispatchProviderInterceptor > FormController::createInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+#ifdef DBG_UTIL
+ // check if we already have a interceptor for the given object
+ for ( ConstInterceptorsIterator aIter = m_aControlDispatchInterceptors.begin();
+ aIter != m_aControlDispatchInterceptors.end();
+ ++aIter
+ )
+ {
+ if ((*aIter)->getIntercepted() == _xInterception)
+ DBG_ERROR("FormController::createInterceptor : we already do intercept this objects dispatches !");
+ }
+#endif
+
+ DispatchInterceptionMultiplexer* pInterceptor = new DispatchInterceptionMultiplexer( _xInterception, this );
+ pInterceptor->acquire();
+ m_aControlDispatchInterceptors.insert( m_aControlDispatchInterceptors.end(), pInterceptor );
+
+ return pInterceptor;
+}
+
+//------------------------------------------------------------------------------
+bool FormController::ensureInteractionHandler()
+{
+ if ( m_xInteractionHandler.is() )
+ return true;
+ if ( m_bAttemptedHandlerCreation )
+ return false;
+ m_bAttemptedHandlerCreation = true;
+
+ m_xInteractionHandler.set( m_aContext.createComponent( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), UNO_QUERY );
+ OSL_ENSURE( m_xInteractionHandler.is(), "FormController::ensureInteractionHandler: could not create an interaction handler!" );
+ return m_xInteractionHandler.is();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest ) throw (RuntimeException)
+{
+ if ( !ensureInteractionHandler() )
+ return;
+ m_xInteractionHandler->handle( _rRequest );
+}
+
+//------------------------------------------------------------------------------
+void FormController::deleteInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
+{
+ OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
+ // search the interceptor responsible for the given object
+ InterceptorsIterator aIter;
+ for ( aIter = m_aControlDispatchInterceptors.begin();
+ aIter != m_aControlDispatchInterceptors.end();
+ ++aIter
+ )
+ {
+ if ((*aIter)->getIntercepted() == _xInterception)
+ break;
+ }
+ if (aIter == m_aControlDispatchInterceptors.end())
+ {
+ return;
+ }
+
+ // log off the interception from it's interception object
+ DispatchInterceptionMultiplexer* pInterceptorImpl = *aIter;
+ pInterceptorImpl->dispose();
+ pInterceptorImpl->release();
+
+ // remove the interceptor from our array
+ m_aControlDispatchInterceptors.erase(aIter);
+}
+
+//--------------------------------------------------------------------
+void FormController::implInvalidateCurrentControlDependentFeatures()
+{
+ Sequence< sal_Int16 > aCurrentControlDependentFeatures(4);
+
+ aCurrentControlDependentFeatures[0] = FormFeature::SortAscending;
+ aCurrentControlDependentFeatures[1] = FormFeature::SortDescending;
+ aCurrentControlDependentFeatures[2] = FormFeature::AutoFilter;
+ aCurrentControlDependentFeatures[3] = FormFeature::RefreshCurrentControl;
+
+ invalidateFeatures( aCurrentControlDependentFeatures );
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ ) throw (RuntimeException)
+{
+ implInvalidateCurrentControlDependentFeatures();
+}
+
+} // namespace svxform
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formcontrolling.cxx b/svx/source/form/formcontrolling.cxx
new file mode 100644
index 000000000000..b76213fe84b7
--- /dev/null
+++ b/svx/source/form/formcontrolling.cxx
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <sal/macros.h>
+#include "formcontrolling.hxx"
+#include "fmurl.hxx"
+#include "svx/svxids.hrc"
+#include "fmprop.hrc"
+#include "svx/fmtools.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/form/runtime/FormOperations.hpp>
+#include <com/sun/star/form/runtime/FormFeature.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
+/** === end UNO includes === **/
+
+#include <tools/diagnose_ex.h>
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <osl/diagnose.h>
+
+#include <functional>
+#include <algorithm>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::form::runtime::XFormController;
+ using ::com::sun::star::form::XForm;
+ using ::com::sun::star::form::runtime::FormOperations;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::sdbc::XRowSet;
+ using ::com::sun::star::form::runtime::FeatureState;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::beans::NamedValue;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::sdb::XSQLErrorBroadcaster;
+ using ::com::sun::star::sdb::SQLErrorEvent;
+ using ::com::sun::star::lang::EventObject;
+ /** === end UNO using === **/
+ namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
+
+ //====================================================================
+ //= FeatureSlotTranslation
+ //====================================================================
+ namespace
+ {
+ struct FeatureDescription
+ {
+ ::rtl::OUString sURL; // the URL
+ sal_Int32 nSlotId; // the SFX-compatible slot ID
+ sal_Int16 nFormFeature; // the css.form.runtime.FormFeature ID
+ };
+ typedef ::std::vector< FeatureDescription > FeatureDescriptions;
+
+ //................................................................
+ const FeatureDescriptions& getFeatureDescriptions()
+ {
+ static FeatureDescriptions s_aFeatureDescriptions;
+ if ( s_aFeatureDescriptions.empty() )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( s_aFeatureDescriptions.empty() )
+ {
+ FeatureDescription aDescriptions[] = {
+ { FMURL_FORM_POSITION, SID_FM_RECORD_ABSOLUTE, FormFeature::MoveAbsolute },
+ { FMURL_FORM_RECORDCOUNT, SID_FM_RECORD_TOTAL, FormFeature::TotalRecords },
+ { FMURL_RECORD_MOVEFIRST, SID_FM_RECORD_FIRST, FormFeature::MoveToFirst },
+ { FMURL_RECORD_MOVEPREV, SID_FM_RECORD_PREV, FormFeature::MoveToPrevious },
+ { FMURL_RECORD_MOVENEXT, SID_FM_RECORD_NEXT, FormFeature::MoveToNext },
+ { FMURL_RECORD_MOVELAST, SID_FM_RECORD_LAST, FormFeature::MoveToLast },
+ { FMURL_RECORD_MOVETONEW, SID_FM_RECORD_NEW, FormFeature::MoveToInsertRow },
+ { FMURL_RECORD_SAVE, SID_FM_RECORD_SAVE, FormFeature::SaveRecordChanges },
+ { FMURL_RECORD_DELETE, SID_FM_RECORD_DELETE, FormFeature::DeleteRecord },
+ { FMURL_FORM_REFRESH, SID_FM_REFRESH, FormFeature::ReloadForm },
+ { FMURL_FORM_REFRESH_CURRENT_CONTROL,
+ SID_FM_REFRESH_FORM_CONTROL,FormFeature::RefreshCurrentControl },
+ { FMURL_RECORD_UNDO, SID_FM_RECORD_UNDO, FormFeature::UndoRecordChanges },
+ { FMURL_FORM_SORT_UP, SID_FM_SORTUP, FormFeature::SortAscending },
+ { FMURL_FORM_SORT_DOWN, SID_FM_SORTDOWN, FormFeature::SortDescending },
+ { FMURL_FORM_SORT, SID_FM_ORDERCRIT, FormFeature::InteractiveSort },
+ { FMURL_FORM_AUTO_FILTER, SID_FM_AUTOFILTER, FormFeature::AutoFilter },
+ { FMURL_FORM_FILTER, SID_FM_FILTERCRIT, FormFeature::InteractiveFilter },
+ { FMURL_FORM_APPLY_FILTER, SID_FM_FORM_FILTERED, FormFeature::ToggleApplyFilter },
+ { FMURL_FORM_REMOVE_FILTER, SID_FM_REMOVE_FILTER_SORT, FormFeature::RemoveFilterAndSort }
+ };
+ for ( size_t i=0; i < SAL_N_ELEMENTS(aDescriptions); ++i )
+ s_aFeatureDescriptions.push_back( aDescriptions[i] );
+ }
+ };
+ return s_aFeatureDescriptions;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ //................................................................
+ struct MatchFeatureDescriptionByURL : public ::std::unary_function< FeatureDescription, bool >
+ {
+ const ::rtl::OUString& m_rURL;
+ MatchFeatureDescriptionByURL( const ::rtl::OUString& _rURL ) :m_rURL( _rURL ) { }
+
+ bool operator()( const FeatureDescription& _compare )
+ {
+ return m_rURL == _compare.sURL;
+ }
+ };
+
+ //................................................................
+ struct MatchFeatureDescriptionBySlotId : public ::std::unary_function< FeatureDescription, bool >
+ {
+ sal_Int32 m_nSlotId;
+ MatchFeatureDescriptionBySlotId( sal_Int32 _nSlotId ) :m_nSlotId( _nSlotId ) { }
+
+ bool operator()( const FeatureDescription& _compare )
+ {
+ return m_nSlotId == _compare.nSlotId;
+ }
+ };
+
+ //................................................................
+ struct MatchFeatureDescriptionByFormFeature : public ::std::unary_function< FeatureDescription, bool >
+ {
+ sal_Int32 m_nFormFeature;
+ MatchFeatureDescriptionByFormFeature( sal_Int32 _nFormFeature ) :m_nFormFeature( _nFormFeature ) { }
+
+ bool operator()( const FeatureDescription& _compare )
+ {
+ return m_nFormFeature == _compare.nFormFeature;
+ }
+ };
+
+ //................................................................
+ struct FormFeatureToSlotId : public ::std::unary_function< sal_Int16, sal_Int32 >
+ {
+ sal_Int32 operator()( sal_Int16 _FormFeature )
+ {
+ return FeatureSlotTranslation::getSlotIdForFormFeature( _FormFeature );
+ }
+ };
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 FeatureSlotTranslation::getControllerFeatureSlotIdForURL( const ::rtl::OUString& _rMainURL )
+ {
+ const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
+ FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByURL( _rMainURL ) );
+ return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString FeatureSlotTranslation::getControllerFeatureURLForSlotId( sal_Int32 _nSlotId )
+ {
+ const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
+ FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
+ OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getControllerFeatureURLForSlotId: not found!" );
+ return ( pos != rDescriptions.end() ) ? pos->sURL : ::rtl::OUString();
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FeatureSlotTranslation::isFeatureURL( const ::rtl::OUString& _rMainURL )
+ {
+ return ( _rMainURL.indexOf( FMURL_FORMSLOTS_PREFIX ) == 0 );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int16 FeatureSlotTranslation::getFormFeatureForSlotId( sal_Int32 _nSlotId )
+ {
+ const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
+ FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
+ OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getFormFeatureForSlotId: not found!" );
+ return ( pos != rDescriptions.end() ) ? pos->nFormFeature : -1;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int32 FeatureSlotTranslation::getSlotIdForFormFeature( sal_Int16 _nFormFeature )
+ {
+ const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
+ FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByFormFeature( _nFormFeature ) );
+ OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getSlotIdForFormFeature: not found!" );
+ return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
+ }
+
+ //====================================================================
+ //= ControllerFeatures
+ //====================================================================
+ //--------------------------------------------------------------------
+ ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, IControllerFeatureInvalidation* _pInvalidationCallback )
+ :m_aContext( _rxORB )
+ ,m_pInvalidationCallback( _pInvalidationCallback )
+ ,m_pImpl( NULL )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
+ const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
+ :m_aContext( _rxORB )
+ ,m_pInvalidationCallback( _pInvalidationCallback )
+ ,m_pImpl( NULL )
+ {
+ assign( _rxController );
+ }
+
+ //--------------------------------------------------------------------
+ ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
+ const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
+ :m_aContext( _rxORB )
+ ,m_pInvalidationCallback( _pInvalidationCallback )
+ ,m_pImpl( NULL )
+ {
+ assign( _rxForm );
+ }
+
+ //--------------------------------------------------------------------
+ void ControllerFeatures::assign( const Reference< XFormController >& _rxController )
+ {
+ dispose();
+ m_pImpl = new FormControllerHelper( m_aContext, _rxController, m_pInvalidationCallback );
+ m_pImpl->acquire();
+ }
+
+ //--------------------------------------------------------------------
+ void ControllerFeatures::assign( const Reference< XForm >& _rxForm )
+ {
+ dispose();
+ m_pImpl = new FormControllerHelper( m_aContext, _rxForm, m_pInvalidationCallback );
+ m_pImpl->acquire();
+ }
+
+ //--------------------------------------------------------------------
+ ControllerFeatures::~ControllerFeatures()
+ {
+ dispose();
+ }
+
+ //--------------------------------------------------------------------
+ void ControllerFeatures::dispose()
+ {
+ if ( m_pImpl )
+ {
+ m_pImpl->dispose();
+ m_pImpl->release();
+ m_pImpl = NULL;
+ }
+ }
+
+ //====================================================================
+ //= FormControllerHelper
+ //====================================================================
+ //--------------------------------------------------------------------
+ FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
+ const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
+ :m_aContext( _rContext )
+ ,m_pInvalidationCallback( _pInvalidationCallback )
+ {
+ osl_incrementInterlockedCount( &m_refCount );
+ try
+ {
+ m_xFormOperations = FormOperations::createWithFormController( m_aContext.getUNOContext(), _rxController );
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->setFeatureInvalidation( this );
+
+ // to prevent the controller from displaying any error messages which happen while we operate on it,
+ // we add ourself as XSQLErrorListener. By contract, a FormController displays errors if and only if
+ // no SQLErrorListeners are registered.
+ Reference< XSQLErrorBroadcaster > xErrorBroadcast( _rxController, UNO_QUERY_THROW );
+ xErrorBroadcast->addSQLErrorListener( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
+ const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
+ :m_aContext( _rContext )
+ ,m_pInvalidationCallback( _pInvalidationCallback )
+ {
+ osl_incrementInterlockedCount( &m_refCount );
+ try
+ {
+ m_xFormOperations = FormOperations::createWithForm( m_aContext.getUNOContext(), _rxForm );
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->setFeatureInvalidation( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+
+ //--------------------------------------------------------------------
+ FormControllerHelper::~FormControllerHelper( )
+ {
+ try
+ {
+ acquire();
+ dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void FormControllerHelper::dispose()
+ {
+ if ( m_xFormOperations.is() )
+ m_xFormOperations->dispose();
+ m_xFormOperations.clear();
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FormControllerHelper::isEnabled( sal_Int32 _nSlotId ) const
+ {
+ if ( !m_xFormOperations.is() )
+ return sal_False;
+ return m_xFormOperations->isEnabled( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XRowSet > FormControllerHelper::getCursor() const
+ {
+ Reference< XRowSet > xCursor;
+ if ( m_xFormOperations.is() )
+ xCursor = m_xFormOperations->getCursor();
+ return xCursor;
+ }
+
+ //--------------------------------------------------------------------
+ void FormControllerHelper::getState( sal_Int32 _nSlotId, FeatureState& _rState ) const
+ {
+ if ( m_xFormOperations.is() )
+ _rState = m_xFormOperations->getState( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FormControllerHelper::commitCurrentControl( ) const
+ {
+ return impl_operateForm_nothrow( COMMIT_CONTROL );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FormControllerHelper::commitCurrentRecord() const
+ {
+ return impl_operateForm_nothrow( COMMIT_RECORD );
+ }
+
+ //--------------------------------------------------------------------
+ bool FormControllerHelper::moveRight( ) const
+ {
+ return impl_operateForm_nothrow( FormFeature::MoveToNext );
+ }
+
+ //--------------------------------------------------------------------
+ bool FormControllerHelper::moveLeft( ) const
+ {
+ return impl_operateForm_nothrow( FormFeature::MoveToPrevious );
+ }
+
+ //--------------------------------------------------------------------
+ void FormControllerHelper::execute( sal_Int32 _nSlotId, const ::rtl::OUString& _rParamName, const Any& _rParamValue ) const
+ {
+ Sequence< NamedValue > aArguments(1);
+ aArguments[0].Name = _rParamName;
+ aArguments[0].Value = _rParamValue;
+
+ impl_operateForm_nothrow( EXECUTE_ARGS, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ), aArguments );
+ }
+
+ //--------------------------------------------------------------------
+ bool FormControllerHelper::impl_operateForm_nothrow( const FormOperation _eWhat, const sal_Int16 _nFeature,
+ const Sequence< NamedValue >& _rArguments ) const
+ {
+ if ( !m_xFormOperations.is() )
+ return false;
+
+ Any aError;
+ bool bSuccess = false;
+ const_cast< FormControllerHelper* >( this )->m_aOperationError.clear();
+ try
+ {
+ switch ( _eWhat )
+ {
+ case COMMIT_CONTROL:
+ bSuccess = m_xFormOperations->commitCurrentControl();
+ break;
+
+ case COMMIT_RECORD:
+ {
+ sal_Bool bDummy( sal_False );
+ bSuccess = m_xFormOperations->commitCurrentRecord( bDummy );
+ }
+ break;
+
+ case EXECUTE:
+ m_xFormOperations->execute( _nFeature );
+ bSuccess = true;
+ break;
+
+ case EXECUTE_ARGS:
+ m_xFormOperations->executeWithArguments( _nFeature, _rArguments );
+ bSuccess = true;
+ break;
+ }
+ }
+ catch ( const SQLException& )
+ {
+ aError = ::cppu::getCaughtException();
+ }
+ catch( const Exception& )
+ {
+ SQLException aFallbackError;
+ aFallbackError.Message = ::comphelper::anyToString( ::cppu::getCaughtException() );
+ aError <<= aFallbackError;
+ }
+
+ if ( bSuccess )
+ return true;
+
+ // display the error. Prefer the one reported in errorOccurred over the one caught.
+ if ( m_aOperationError.hasValue() )
+ displayException( m_aOperationError );
+ else if ( aError.hasValue() )
+ displayException( aError );
+ else
+ OSL_ENSURE( false, "FormControllerHelper::impl_operateForm_nothrow: no success, but no error?" );
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ void FormControllerHelper::execute( sal_Int32 _nSlotId ) const
+ {
+ impl_operateForm_nothrow( EXECUTE, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ),
+ Sequence< NamedValue >() );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormControllerHelper::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException)
+ {
+ if ( !m_pInvalidationCallback )
+ // nobody's interested in ...
+ return;
+
+ ::std::vector< sal_Int32 > aFeatures( _Features.getLength() );
+ ::std::transform(
+ _Features.getConstArray(),
+ _Features.getConstArray() + _Features.getLength(),
+ aFeatures.begin(),
+ FormFeatureToSlotId()
+ );
+
+ m_pInvalidationCallback->invalidateFeatures( aFeatures );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormControllerHelper::invalidateAllFeatures() throw (RuntimeException)
+ {
+ if ( !m_pInvalidationCallback )
+ // nobody's interested in ...
+ return;
+
+ // actually, it's a little bit more than the supported features,
+ // but on the medium term, we are to support everything listed
+ // here
+ ::std::vector< sal_Int32 > aSupportedFeatures;
+ sal_Int32 pSupportedFeatures[] =
+ {
+ SID_FM_RECORD_FIRST,
+ SID_FM_RECORD_NEXT,
+ SID_FM_RECORD_PREV,
+ SID_FM_RECORD_LAST,
+ SID_FM_RECORD_NEW,
+ SID_FM_RECORD_DELETE,
+ SID_FM_RECORD_ABSOLUTE,
+ SID_FM_RECORD_TOTAL,
+ SID_FM_RECORD_SAVE,
+ SID_FM_RECORD_UNDO,
+ SID_FM_REMOVE_FILTER_SORT,
+ SID_FM_SORTUP,
+ SID_FM_SORTDOWN,
+ SID_FM_ORDERCRIT,
+ SID_FM_AUTOFILTER,
+ SID_FM_FILTERCRIT,
+ SID_FM_FORM_FILTERED,
+ SID_FM_REFRESH,
+ SID_FM_REFRESH_FORM_CONTROL,
+ SID_FM_SEARCH,
+ SID_FM_FILTER_START,
+ SID_FM_VIEW_AS_GRID
+ };
+ sal_Int32 nFeatureCount = SAL_N_ELEMENTS( pSupportedFeatures );
+ aSupportedFeatures.resize( nFeatureCount );
+ ::std::copy( pSupportedFeatures, pSupportedFeatures + nFeatureCount, aSupportedFeatures.begin() );
+
+ m_pInvalidationCallback->invalidateFeatures( aSupportedFeatures );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormControllerHelper::errorOccured( const SQLErrorEvent& _Event ) throw (RuntimeException)
+ {
+ OSL_ENSURE( !m_aOperationError.hasValue(), "FormControllerHelper::errorOccurred: two errors during one operation?" );
+ m_aOperationError = _Event.Reason;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL FormControllerHelper::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
+ {
+ // not interested in
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FormControllerHelper::isInsertionRow() const
+ {
+ sal_Bool bIs = sal_False;
+ if ( m_xFormOperations.is() )
+ bIs = m_xFormOperations->isInsertionRow();
+ return bIs;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool FormControllerHelper::isModifiedRow() const
+ {
+ sal_Bool bIs = sal_False;
+ if ( m_xFormOperations.is() )
+ bIs = m_xFormOperations->isModifiedRow();
+ return bIs;
+ }
+ //--------------------------------------------------------------------
+ bool FormControllerHelper::canDoFormFilter() const
+ {
+ if ( !m_xFormOperations.is() )
+ return false;
+
+ bool bCanDo = false;
+ try
+ {
+ Reference< XPropertySet > xCursorProperties( m_xFormOperations->getCursor(), UNO_QUERY_THROW );
+
+ bool bEscapeProcessing( false );
+ OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
+
+ ::rtl::OUString sActiveCommand;
+ OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ACTIVECOMMAND ) >>= sActiveCommand );
+
+ bool bInsertOnlyForm( false );
+ OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_INSERTONLY ) >>= bInsertOnlyForm );
+
+ bCanDo = bEscapeProcessing && ( sActiveCommand.getLength() > 0 ) && !bInsertOnlyForm;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return bCanDo;
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formdispatchinterceptor.cxx b/svx/source/form/formdispatchinterceptor.cxx
new file mode 100644
index 000000000000..7eff1ac6bc8b
--- /dev/null
+++ b/svx/source/form/formdispatchinterceptor.cxx
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "formdispatchinterceptor.hxx"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+
+#include <tools/debug.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::frame::XDispatchProviderInterception;
+ using ::com::sun::star::frame::XDispatchProviderInterceptor;
+ using ::com::sun::star::lang::XComponent;
+ using ::com::sun::star::util::URL;
+ using ::com::sun::star::frame::XDispatch;
+ using ::com::sun::star::frame::DispatchDescriptor;
+ using ::com::sun::star::frame::XDispatchProvider;
+ using ::com::sun::star::lang::EventObject;
+ /** === end UNO using === **/
+
+ //========================================================================
+ //= DispatchInterceptionMultiplexer
+ //========================================================================
+
+ DBG_NAME(DispatchInterceptionMultiplexer)
+ //------------------------------------------------------------------------
+ DispatchInterceptionMultiplexer::DispatchInterceptionMultiplexer(
+ const Reference< XDispatchProviderInterception >& _rxToIntercept, DispatchInterceptor* _pMaster )
+ :DispatchInterceptionMultiplexer_BASE(_pMaster && _pMaster->getInterceptorMutex() ? *_pMaster->getInterceptorMutex() : m_aFallback)
+ ,m_aFallback()
+ ,m_pMutex( _pMaster && _pMaster->getInterceptorMutex() ? _pMaster->getInterceptorMutex() : &m_aFallback )
+ ,m_xIntercepted(_rxToIntercept)
+ ,m_bListening(sal_False)
+ ,m_pMaster(_pMaster)
+ {
+ DBG_CTOR(DispatchInterceptionMultiplexer,NULL);
+
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ ::comphelper::increment(m_refCount);
+ if (_rxToIntercept.is())
+ {
+ _rxToIntercept->registerDispatchProviderInterceptor((XDispatchProviderInterceptor*)this);
+ // this should make us the top-level dispatch-provider for the component, via a call to our
+ // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
+ Reference< XComponent> xInterceptedComponent(_rxToIntercept, UNO_QUERY);
+ if (xInterceptedComponent.is())
+ {
+ xInterceptedComponent->addEventListener(this);
+ m_bListening = sal_True;
+ }
+ }
+ ::comphelper::decrement(m_refCount);
+ }
+
+ //------------------------------------------------------------------------
+ DispatchInterceptionMultiplexer::~DispatchInterceptionMultiplexer()
+ {
+ if (!rBHelper.bDisposed)
+ dispose();
+
+ DBG_DTOR(DispatchInterceptionMultiplexer,NULL);
+ }
+
+ //------------------------------------------------------------------------------
+ Reference< XDispatch > SAL_CALL DispatchInterceptionMultiplexer::queryDispatch( const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags ) throw(RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ Reference< XDispatch> xResult;
+ // ask our 'real' interceptor
+ if (m_pMaster)
+ xResult = m_pMaster->interceptedQueryDispatch( aURL, aTargetFrameName, nSearchFlags);
+
+ // ask our slave provider
+ if (!xResult.is() && m_xSlaveDispatcher.is())
+ xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
+
+ return xResult;
+ }
+
+ //------------------------------------------------------------------------------
+ Sequence< Reference< XDispatch > > SAL_CALL
+ DispatchInterceptionMultiplexer::queryDispatches( const Sequence< DispatchDescriptor >& aDescripts ) throw(RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ Sequence< Reference< XDispatch> > aReturn(aDescripts.getLength());
+ Reference< XDispatch>* pReturn = aReturn.getArray();
+ const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
+ for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
+ {
+ *pReturn = queryDispatch(pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags);
+ }
+ return aReturn;
+ }
+
+ //------------------------------------------------------------------------------
+ Reference< XDispatchProvider > SAL_CALL DispatchInterceptionMultiplexer::getSlaveDispatchProvider( ) throw(RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return m_xSlaveDispatcher;
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL DispatchInterceptionMultiplexer::setSlaveDispatchProvider(const Reference< XDispatchProvider>& xNewDispatchProvider) throw( RuntimeException )
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ m_xSlaveDispatcher = xNewDispatchProvider;
+ }
+
+ //------------------------------------------------------------------------------
+ Reference< XDispatchProvider> SAL_CALL DispatchInterceptionMultiplexer::getMasterDispatchProvider(void) throw( RuntimeException )
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ return m_xMasterDispatcher;
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL DispatchInterceptionMultiplexer::setMasterDispatchProvider(const Reference< XDispatchProvider>& xNewSupplier) throw( RuntimeException )
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ m_xMasterDispatcher = xNewSupplier;
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL DispatchInterceptionMultiplexer::disposing(const EventObject& Source) throw( RuntimeException )
+ {
+ if (m_bListening)
+ {
+ Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
+ if (Source.Source == xIntercepted)
+ ImplDetach();
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ void DispatchInterceptionMultiplexer::ImplDetach()
+ {
+ ::osl::MutexGuard aGuard( *m_pMutex );
+ OSL_ENSURE(m_bListening, "DispatchInterceptionMultiplexer::ImplDetach: invalid call!");
+
+ // deregister ourself from the interception component
+ Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
+ if (xIntercepted.is())
+ xIntercepted->releaseDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
+
+ // m_xIntercepted = Reference< XDispatchProviderInterception >();
+ // Don't reset m_xIntercepted: It may be needed by our owner to check for which object we were
+ // responsible. As we hold the object with a weak reference only, this should be no problem.
+ // 88936 - 23.07.2001 - frank.schoenheit@sun.com
+ m_pMaster = NULL;
+ m_pMutex = &m_aFallback;
+ m_bListening = sal_False;
+ }
+
+ //------------------------------------------------------------------------------
+ void DispatchInterceptionMultiplexer::disposing()
+ {
+ // remove ourself as event listener from the interception component
+ if (m_bListening)
+ {
+ Reference< XComponent> xInterceptedComponent(m_xIntercepted.get(), UNO_QUERY);
+ if (xInterceptedComponent.is())
+ xInterceptedComponent->removeEventListener(static_cast<XEventListener*>(this));
+
+ // detach from the interception component
+ ImplDetach();
+ }
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formfeaturedispatcher.cxx b/svx/source/form/formfeaturedispatcher.cxx
new file mode 100644
index 000000000000..b7277ce6dd6c
--- /dev/null
+++ b/svx/source/form/formfeaturedispatcher.cxx
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "formfeaturedispatcher.hxx"
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <tools/diagnose_ex.h>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::form::runtime;
+
+ //====================================================================
+ //= OSingleFeatureDispatcher
+ //====================================================================
+ //--------------------------------------------------------------------
+ OSingleFeatureDispatcher::OSingleFeatureDispatcher( const URL& _rFeatureURL, const sal_Int16 _nFormFeature,
+ const Reference< XFormOperations >& _rxFormOperations, ::osl::Mutex& _rMutex )
+ :m_rMutex( _rMutex )
+ ,m_aStatusListeners( _rMutex )
+ ,m_xFormOperations( _rxFormOperations )
+ ,m_aFeatureURL( _rFeatureURL )
+ ,m_nFormFeature( _nFormFeature )
+ ,m_bLastKnownEnabled( sal_False )
+ ,m_bDisposed( sal_False )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void OSingleFeatureDispatcher::dispose()
+ {
+ {
+ ::osl::MutexGuard aGuard( m_rMutex );
+ if ( m_bDisposed )
+ return;
+ }
+
+ EventObject aDisposeEvent( *this );
+ m_aStatusListeners.disposeAndClear( aDisposeEvent );
+
+ {
+ ::osl::MutexGuard aGuard( m_rMutex );
+ m_bDisposed = sal_True;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void OSingleFeatureDispatcher::getUnoState( FeatureStateEvent& /* [out] */ _rState ) const
+ {
+ _rState.Source = *const_cast< OSingleFeatureDispatcher* >( this );
+
+ FeatureState aState( m_xFormOperations->getState( m_nFormFeature ) );
+
+ _rState.FeatureURL = m_aFeatureURL;
+ _rState.IsEnabled = aState.Enabled;
+ _rState.Requery = sal_False;
+ _rState.State = aState.State;
+ }
+
+ //--------------------------------------------------------------------
+ void OSingleFeatureDispatcher::updateAllListeners()
+ {
+ ::osl::ClearableMutexGuard aGuard( m_rMutex );
+
+ FeatureStateEvent aUnoState;
+ getUnoState( aUnoState );
+
+ if ( ( m_aLastKnownState == aUnoState.State ) && ( m_bLastKnownEnabled == aUnoState.IsEnabled ) )
+ return;
+
+ m_aLastKnownState = aUnoState.State;
+ m_bLastKnownEnabled = aUnoState.IsEnabled;
+
+ notifyStatus( NULL, aGuard );
+ }
+
+ //--------------------------------------------------------------------
+ void OSingleFeatureDispatcher::notifyStatus( const Reference< XStatusListener >& _rxListener, ::osl::ClearableMutexGuard& _rFreeForNotification )
+ {
+ FeatureStateEvent aUnoState;
+ getUnoState( aUnoState );
+
+ if ( _rxListener.is() )
+ {
+ try
+ {
+ _rFreeForNotification.clear();
+ _rxListener->statusChanged( aUnoState );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught an exception!" );
+ }
+ }
+ else
+ {
+ ::cppu::OInterfaceIteratorHelper aIter( m_aStatusListeners );
+ _rFreeForNotification.clear();
+
+ while ( aIter.hasMoreElements() )
+ {
+ try
+ {
+ static_cast< XStatusListener* >( aIter.next() )->statusChanged( aUnoState );
+ }
+ catch( const DisposedException& )
+ {
+ OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a DisposedException - removing the listener!" );
+ aIter.remove( );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "OSingleFeatureDispatcher::notifyStatus: caught a generic exception while notifying a single listener!" );
+ }
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OSingleFeatureDispatcher::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException)
+ {
+ ::osl::ClearableMutexGuard aGuard( m_rMutex );
+ checkAlive();
+
+ OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::dispatch: not responsible for this URL!" );
+ (void)_rURL;
+
+ if ( !m_xFormOperations->isEnabled( m_nFormFeature ) )
+ return;
+
+ // release our mutex before executing the command
+ sal_Int16 nFormFeature( m_nFormFeature );
+ Reference< XFormOperations > xFormOperations( m_xFormOperations );
+ aGuard.clear();
+
+ try
+ {
+ if ( !_rArguments.getLength() )
+ {
+ xFormOperations->execute( nFormFeature );
+ }
+ else
+ { // at the moment we only support one parameter
+ ::comphelper::NamedValueCollection aArgs( _rArguments );
+ xFormOperations->executeWithArguments( nFormFeature, aArgs.getNamedValues() );
+ }
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OSingleFeatureDispatcher::addStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException)
+ {
+ (void)_rURL;
+ OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::addStatusListener: unexpected URL!" );
+ OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::addStatusListener: senseless call!" );
+ if ( !_rxControl.is() )
+ return;
+
+ ::osl::ClearableMutexGuard aGuard( m_rMutex );
+ if ( m_bDisposed )
+ {
+ EventObject aDisposeEvent( *this );
+ aGuard.clear();
+ _rxControl->disposing( aDisposeEvent );
+ return;
+ }
+
+ m_aStatusListeners.addInterface( _rxControl );
+
+ // initially update the status
+ notifyStatus( _rxControl, aGuard );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OSingleFeatureDispatcher::removeStatusListener( const Reference< XStatusListener >& _rxControl, const URL& _rURL ) throw (RuntimeException)
+ {
+ (void)_rURL;
+ OSL_ENSURE( _rURL.Complete == m_aFeatureURL.Complete, "OSingleFeatureDispatcher::removeStatusListener: unexpected URL!" );
+ OSL_ENSURE( _rxControl.is(), "OSingleFeatureDispatcher::removeStatusListener: senseless call!" );
+ if ( !_rxControl.is() )
+ return;
+
+ ::osl::MutexGuard aGuard( m_rMutex );
+ checkAlive();
+
+ m_aStatusListeners.removeInterface( _rxControl );
+ }
+
+ //--------------------------------------------------------------------
+ void OSingleFeatureDispatcher::checkAlive() const SAL_THROW((DisposedException))
+ {
+ if ( m_bDisposed )
+ throw DisposedException( ::rtl::OUString(), *const_cast< OSingleFeatureDispatcher* >( this ) );
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/formshell.src b/svx/source/form/formshell.src
new file mode 100644
index 000000000000..5a7e25e14f13
--- /dev/null
+++ b/svx/source/form/formshell.src
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "fmresids.hrc"
+#include <svx/svxids.hrc>
+#include <svx/dialogs.hrc>
+#include <sfx2/sfxsids.hrc>
+#include "globlmn.hrc"
+#include "helpid.hrc"
+
+Menu RID_FM_TEXTATTRIBUTE_MENU
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_FONT
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_FONTHEIGHT
+ };
+ MenuItem
+ {
+ Identifier = MENU_FM_TEXTATTRIBITES_STYLE;
+ HelpID = MENU_FM_TEXTATTRIBITES_STYLE;
+ Text [ en-US ] = "St~yle";
+ SubMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_WEIGHT
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_POSTURE
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_OVERLINE
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_UNDERLINE
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_STRIKEOUT
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_SHADOWED
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_CHAR_CONTOUR
+ };
+ MenuItem { Separator = TRUE; };
+ MenuItem
+ {
+ ITEM_FORMAT_SET_SUPER_SCRIPT
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_SET_SUB_SCRIPT
+ };
+ };
+ };
+ };
+ MenuItem
+ {
+ Identifier = MENU_FM_TEXTATTRIBITES_ALIGNMENT;
+ HelpID = MENU_FM_TEXTATTRIBITES_ALIGNMENT;
+ Text [ en-US ] = "~Alignment";
+ RadioCheck = TRUE;
+ SubMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_ATTR_PARA_ADJUST_LEFT
+ };
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_ATTR_PARA_ADJUST_RIGHT
+ };
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_ATTR_PARA_ADJUST_CENTER
+ };
+ MenuItem
+ {
+ ITEM_FORMAT_ATTR_PARA_ADJUST_BLOCK
+ RadioCheck = TRUE;
+ };
+ };
+ };
+ };
+ MenuItem
+ {
+ Identifier = MENU_FM_TEXTATTRIBITES_SPACING;
+ HelpID = MENU_FM_TEXTATTRIBITES_SPACING;
+ Text [ en-US ] = "~Line Spacing";
+ _MenuItemFlags = MIB_RADIOCHECK;
+ SubMenu = Menu
+ {
+ ItemList =
+ {
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_PARA_LINESPACE_10
+ };
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_PARA_LINESPACE_15
+ };
+ MenuItem
+ {
+ RadioCheck = TRUE;
+ ITEM_FORMAT_PARA_LINESPACE_20
+ };
+ };
+ };
+ };
+ };
+};
+
+TabDialog RID_SVXDLG_TEXTCONTROL_CHARATTR
+{
+ OutputSize = TRUE;
+ SVLook = TRUE;
+ Moveable = TRUE;
+
+ Text [ en-US ] = "Character";
+
+ TabControl 1
+ {
+ OutputSize = TRUE;
+ PageList =
+ {
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_CHAR_NAME;
+ Text [ en-US ] = "Font";
+ };
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_CHAR_EFFECTS;
+ Text [ en-US ] = "Font Effects";
+ };
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_CHAR_POSITION;
+ Text [ en-US ] = "Position";
+ };
+ };
+ };
+};
+
+TabDialog RID_SVXDLG_TEXTCONTROL_PARAATTR
+{
+ OutputSize = TRUE;
+ SVLook = TRUE;
+ Moveable = TRUE;
+
+ Text [ en-US ] = "Paragraph";
+
+ TabControl 1
+ {
+ OutputSize = TRUE;
+ PageList =
+ {
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_STD_PARAGRAPH;
+ Text [ en-US ] = "Indents & Spacing";
+ };
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_ALIGN_PARAGRAPH;
+ Text [ en-US ] = "Alignment";
+ };
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_PARA_ASIAN;
+ Text [ en-US ] = "Asian Typography";
+ };
+ PageItem
+ {
+ Identifier = RID_SVXPAGE_TABULATOR;
+ Text [ en-US ] = "Tabs";
+ };
+ };
+ };
+};
diff --git a/svx/source/form/formtoolbars.cxx b/svx/source/form/formtoolbars.cxx
new file mode 100644
index 000000000000..063e3e01005c
--- /dev/null
+++ b/svx/source/form/formtoolbars.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "formtoolbars.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/XPropertySet.hpp>
+/** === end UNO includes === **/
+
+#include <svx/svxids.hrc>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::frame;
+
+ //====================================================================
+ //= FormToolboxes
+ //====================================================================
+ //--------------------------------------------------------------------
+ FormToolboxes::FormToolboxes( const Reference< XFrame >& _rxFrame )
+ {
+ // the layout manager
+ Reference< XPropertySet > xFrameProps( _rxFrame, UNO_QUERY );
+ if ( xFrameProps.is() )
+ xFrameProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) ) ) >>= m_xLayouter;
+ }
+
+ //--------------------------------------------------------------------
+ void FormToolboxes::toggleToolbox( USHORT _nSlotId ) const
+ {
+ try
+ {
+ Reference< XLayoutManager > xManager( m_xLayouter );
+ OSL_ENSURE( xManager. is(), "FormToolboxes::toggleToolbox: couldn't obtain the layout manager!" );
+ if ( xManager. is() )
+ {
+ ::rtl::OUString sToolboxResource( getToolboxResourceName( _nSlotId ) );
+ if ( xManager->isElementVisible( sToolboxResource ) )
+ {
+ xManager->hideElement( sToolboxResource );
+ xManager->destroyElement( sToolboxResource );
+ }
+ else
+ {
+ xManager->createElement( sToolboxResource );
+ xManager->showElement( sToolboxResource );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FormToolboxes::toggleToolbox: caught an exception!" );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ bool FormToolboxes::isToolboxVisible( USHORT _nSlotId ) const
+ {
+ return m_xLayouter.is() && m_xLayouter->isElementVisible(
+ getToolboxResourceName( _nSlotId ) );
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString FormToolboxes::getToolboxResourceName( USHORT _nSlotId ) const
+ {
+ OSL_ENSURE( ( _nSlotId == SID_FM_MORE_CONTROLS ) || ( _nSlotId == SID_FM_FORM_DESIGN_TOOLS ) || ( _nSlotId == SID_FM_CONFIG ),
+ "FormToolboxes::getToolboxResourceName: unsupported slot!" );
+
+ const sal_Char* pToolBarName = "formcontrols";
+ if ( _nSlotId == SID_FM_MORE_CONTROLS )
+ pToolBarName = "moreformcontrols";
+ else if ( _nSlotId == SID_FM_FORM_DESIGN_TOOLS )
+ pToolBarName = "formdesign";
+
+ ::rtl::OUString aToolBarResStr( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/" ));
+ aToolBarResStr += ::rtl::OUString::createFromAscii( pToolBarName );
+ return aToolBarResStr;
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/legacyformcontroller.cxx b/svx/source/form/legacyformcontroller.cxx
new file mode 100644
index 000000000000..2224ce7caa2f
--- /dev/null
+++ b/svx/source/form/legacyformcontroller.cxx
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "fmservs.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/form/XFormController.hpp>
+#include <com/sun/star/form/runtime/XFormController.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+/** === end UNO includes === **/
+
+#include <cppuhelper/implbase2.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::awt::XControl;
+ using ::com::sun::star::awt::XTabControllerModel;
+ using ::com::sun::star::awt::XControlContainer;
+ using ::com::sun::star::lang::XServiceInfo;
+ /** === end UNO using === **/
+
+ using namespace ::com::sun::star;
+
+ //====================================================================
+ //= LegacyFormController
+ //====================================================================
+ typedef ::cppu::WeakImplHelper2 < form::XFormController
+ , XServiceInfo
+ > LegacyFormController_Base;
+ /** is an implementation of the legacy form controller service, namely css.form.FormController, supporting the
+ css.form.XFormController interface.
+
+ This legacy API is superseded by css.form.runtime.(X)FormController, and though we migrated all OOo-internal
+ usage of this old API, their might be clients external to OOo still using it (though this is rather unlikely).
+ */
+ class LegacyFormController : public LegacyFormController_Base
+ {
+ public:
+ static Reference< XInterface > Create( const Reference< XMultiServiceFactory >& _rxFactory )
+ {
+ return *( new LegacyFormController( _rxFactory ) );
+ }
+
+ protected:
+ LegacyFormController( const Reference< XMultiServiceFactory >& _rxFactory )
+ :m_xDelegator( _rxFactory->createInstance( FM_FORM_CONTROLLER ), UNO_QUERY_THROW )
+ {
+ }
+
+ // form::XFormController
+ virtual Reference< XControl > SAL_CALL getCurrentControl( ) throw (RuntimeException);
+ virtual void SAL_CALL addActivateListener( const Reference< form::XFormControllerListener >& l ) throw (RuntimeException);
+ virtual void SAL_CALL removeActivateListener( const Reference< form::XFormControllerListener >& l ) throw (RuntimeException);
+
+ // awt::XTabController
+ virtual void SAL_CALL setModel( const Reference< XTabControllerModel >& Model ) throw (RuntimeException);
+ virtual Reference< XTabControllerModel > SAL_CALL getModel( ) throw (RuntimeException);
+ virtual void SAL_CALL setContainer( const Reference< XControlContainer >& Container ) throw (RuntimeException);
+ virtual Reference< XControlContainer > SAL_CALL getContainer( ) throw (RuntimeException);
+ virtual Sequence< Reference< XControl > > SAL_CALL getControls( ) throw (RuntimeException);
+ virtual void SAL_CALL autoTabOrder( ) throw (RuntimeException);
+ virtual void SAL_CALL activateTabOrder( ) throw (RuntimeException);
+ virtual void SAL_CALL activateFirst( ) throw (RuntimeException);
+ virtual void SAL_CALL activateLast( ) throw (RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException);
+ virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
+ virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException);
+
+ private:
+ const Reference< form::runtime::XFormController > m_xDelegator;
+ };
+
+ //--------------------------------------------------------------------
+ Reference< XControl > SAL_CALL LegacyFormController::getCurrentControl( ) throw (RuntimeException)
+ {
+ return m_xDelegator->getCurrentControl();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::addActivateListener( const Reference< form::XFormControllerListener >& _listener ) throw (RuntimeException)
+ {
+ m_xDelegator->addActivateListener( _listener );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::removeActivateListener( const Reference< form::XFormControllerListener >& _listener ) throw (RuntimeException)
+ {
+ m_xDelegator->removeActivateListener( _listener );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::setModel( const Reference< XTabControllerModel >& _model ) throw (RuntimeException)
+ {
+ m_xDelegator->setModel( _model );
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XTabControllerModel > SAL_CALL LegacyFormController::getModel( ) throw (RuntimeException)
+ {
+ return m_xDelegator->getModel();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::setContainer( const Reference< XControlContainer >& _container ) throw (RuntimeException)
+ {
+ m_xDelegator->setContainer( _container );
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XControlContainer > SAL_CALL LegacyFormController::getContainer( ) throw (RuntimeException)
+ {
+ return m_xDelegator->getContainer();
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< Reference< XControl > > SAL_CALL LegacyFormController::getControls( ) throw (RuntimeException)
+ {
+ return m_xDelegator->getControls();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::autoTabOrder( ) throw (RuntimeException)
+ {
+ m_xDelegator->autoTabOrder();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::activateTabOrder( ) throw (RuntimeException)
+ {
+ m_xDelegator->activateTabOrder();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::activateFirst( ) throw (RuntimeException)
+ {
+ m_xDelegator->activateFirst();
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL LegacyFormController::activateLast( ) throw (RuntimeException)
+ {
+ m_xDelegator->activateLast();
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString SAL_CALL LegacyFormController::getImplementationName( ) throw (RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.svx.LegacyFormController" ) );
+ }
+
+ //--------------------------------------------------------------------
+ ::sal_Bool SAL_CALL LegacyFormController::supportsService( const ::rtl::OUString& _serviceName ) throw (RuntimeException)
+ {
+ Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() );
+ const ::rtl::OUString* pServices = aServices.getConstArray();
+ for ( sal_Int32 i = 0; i < aServices.getLength(); ++i, ++pServices )
+ if( pServices->equals( _serviceName ) )
+ return sal_True;
+ return sal_False;
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< ::rtl::OUString > SAL_CALL LegacyFormController::getSupportedServiceNames( ) throw (RuntimeException)
+ {
+ Sequence< ::rtl::OUString > aServices(2);
+ aServices.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.FormController" ) );
+ aServices.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.control.TabController") );
+ return aServices;
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+//------------------------------------------------------------------
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
+ LegacyFormController_NewInstance_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & _rxORB )
+{
+ return ::svxform::LegacyFormController::Create( _rxORB );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/makefile.mk b/svx/source/form/makefile.mk
new file mode 100644
index 000000000000..44bcd53d234f
--- /dev/null
+++ b/svx/source/form/makefile.mk
@@ -0,0 +1,123 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=svx
+TARGET=form
+LIBTARGET=NO
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(ENABLE_VBA)"=="YES"
+ CDEFS+=-DENABLE_VBA
+.ENDIF
+
+.IF "$(ENABLE_VBA)"=="YES"
+ CDEFS+=-DENABLE_VBA
+.ENDIF
+
+SRS1NAME=form
+SRC1FILES= \
+ fmexpl.src \
+ filtnav.src \
+ fmstring.src \
+ formshell.src \
+ datanavi.src
+
+LIB1TARGET= $(SLB)$/$(TARGET)-core.lib
+LIB1OBJFILES= \
+ $(SLO)$/formtoolbars.obj \
+ $(SLO)$/fmdocumentclassification.obj \
+ $(SLO)$/fmcontrolbordermanager.obj \
+ $(SLO)$/fmcontrollayout.obj \
+ $(SLO)$/fmtextcontroldialogs.obj \
+ $(SLO)$/fmtextcontrolfeature.obj \
+ $(SLO)$/fmtextcontrolshell.obj \
+ $(SLO)$/ParseContext.obj \
+ $(SLO)$/typeconversionclient.obj \
+ $(SLO)$/dbtoolsclient.obj \
+ $(SLO)$/sqlparserclient.obj \
+ $(SLO)$/dataaccessdescriptor.obj \
+ $(SLO)$/fmpage.obj \
+ $(SLO)$/fmundo.obj \
+ $(SLO)$/fmmodel.obj \
+ $(SLO)$/navigatortree.obj \
+ $(SLO)$/navigatortreemodel.obj \
+ $(SLO)$/fmexpl.obj \
+ $(SLO)$/formcontroller.obj \
+ $(SLO)$/fmpgeimp.obj \
+ $(SLO)$/fmvwimp.obj \
+ $(SLO)$/fmdpage.obj \
+ $(SLO)$/fmitems.obj \
+ $(SLO)$/fmobj.obj \
+ $(SLO)$/fmdmod.obj \
+ $(SLO)$/fmservs.obj \
+ $(SLO)$/typemap.obj \
+ $(SLO)$/fmexch.obj \
+ $(SLO)$/fmtools.obj \
+ $(SLO)$/fmshimp.obj \
+ $(SLO)$/fmshell.obj \
+ $(SLO)$/fmview.obj \
+ $(SLO)$/sdbdatacolumn.obj \
+ $(SLO)$/formcontrolling.obj \
+ $(SLO)$/formfeaturedispatcher.obj \
+ $(SLO)$/formdispatchinterceptor.obj \
+ $(SLO)$/datanavi.obj \
+ $(SLO)$/xfm_addcondition.obj \
+ $(SLO)$/datalistener.obj \
+ $(SLO)$/fmscriptingenv.obj \
+ $(SLO)$/stringlistresource.obj \
+ $(SLO)$/delayedevent.obj \
+ $(SLO)$/formcontrolfactory.obj \
+ $(SLO)$/legacyformcontroller.obj
+
+LIB2TARGET= $(SLB)$/$(TARGET).lib
+LIB2OBJFILES= \
+ $(SLO)$/dbcharsethelper.obj \
+ $(SLO)$/fmPropBrw.obj \
+ $(SLO)$/tbxform.obj \
+ $(SLO)$/fmobjfac.obj \
+ $(SLO)$/fmsrccfg.obj \
+ $(SLO)$/tabwin.obj \
+ $(SLO)$/filtnav.obj \
+ $(SLO)$/fmsrcimp.obj \
+ $(SLO)$/databaselocationinput.obj
+
+SLOFILES = $(LIB1OBJFILES) $(LIB2OBJFILES)
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/svx/source/form/navigatortree.cxx b/svx/source/form/navigatortree.cxx
new file mode 100644
index 000000000000..df01af4bfa0d
--- /dev/null
+++ b/svx/source/form/navigatortree.cxx
@@ -0,0 +1,2301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/dialmgr.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/fmpage.hxx>
+#include <svx/svdpagv.hxx>
+#include "svditer.hxx"
+
+#include "fmhelp.hrc"
+#include "fmexpl.hrc"
+#include "fmexpl.hxx"
+#include "fmresids.hrc"
+#include "fmshimp.hxx"
+#include "fmservs.hxx"
+#include "fmundo.hxx"
+#include "fmpgeimp.hxx"
+#include "fmitems.hxx"
+#include "fmobj.hxx"
+#include "fmprop.hrc"
+#include <vcl/wrkwin.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/script/XEventAttacherManager.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <sdrpaintwindow.hxx>
+
+#include <svx/svxdlg.hxx>
+#include <svx/dialogs.hrc>
+#include <rtl/logfile.hxx>
+//............................................................................
+namespace svxform
+{
+//............................................................................
+
+ #define DROP_ACTION_TIMER_INITIAL_TICKS 10
+ // solange dauert es, bis das Scrollen anspringt
+ #define DROP_ACTION_TIMER_SCROLL_TICKS 3
+ // in diesen Intervallen wird jeweils eine Zeile gescrollt
+ #define DROP_ACTION_TIMER_TICK_BASE 10
+ // das ist die Basis, mit der beide Angaben multipliziert werden (in ms)
+
+ #define EXPLORER_SYNC_DELAY 200
+ // dieser Betrag an Millisekunden wird gewartet, ehe der Explorer nach einem Select oder Deselect die ::com::sun::star::sdbcx::View synchronisiert
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::form;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::script;
+ using namespace ::com::sun::star::datatransfer;
+ using namespace ::com::sun::star::datatransfer::clipboard;
+ using namespace ::com::sun::star::sdb;
+
+ //========================================================================
+ // helper
+ //========================================================================
+
+ typedef ::std::map< Reference< XInterface >, SdrObject*, ::comphelper::OInterfaceCompare< XInterface > >
+ MapModelToShape;
+ typedef MapModelToShape::value_type ModelShapePair;
+
+ //------------------------------------------------------------------------
+ void collectShapeModelMapping( SdrPage* _pPage, MapModelToShape& _rMapping )
+ {
+ OSL_ENSURE( _pPage, "collectShapeModelMapping: invalid arg!" );
+
+ _rMapping.clear();
+
+ SdrObjListIter aIter( *_pPage );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pSdrObject = aIter.Next();
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
+ if ( !pFormObject )
+ continue;
+
+ Reference< XInterface > xNormalizedModel( pFormObject->GetUnoControlModel(), UNO_QUERY );
+ // note that this is normalized (i.e. queried for XInterface explicitly)
+
+#ifdef DBG_UTIL
+ ::std::pair< MapModelToShape::iterator, bool > aPos =
+#endif
+ _rMapping.insert( ModelShapePair( xNormalizedModel, pSdrObject ) );
+ DBG_ASSERT( aPos.second, "collectShapeModelMapping: model was already existent!" );
+ // if this asserts, this would mean we have 2 shapes pointing to the same model
+ }
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool isModelShapeMarked( FmEntryData* _pEntry, const MapModelToShape& _rModelMap, SdrMarkView* _pView )
+ {
+ DBG_ASSERT( _pEntry && _pView, "isModelShapeMarked: invalid arguments!" );
+ if ( !_pEntry || !_pView )
+ return sal_False;
+
+ DBG_ASSERT( _pEntry->GetElement().get() == Reference< XInterface >( _pEntry->GetElement(), UNO_QUERY ).get(),
+ "isModelShapeMarked: element of the FmEntryData is not normalized!" );
+ // normalization of the XInterface is a prerequisite for properly finding it in the map
+
+ sal_Bool bIsMarked = sal_False;
+
+ MapModelToShape::const_iterator aPos = _rModelMap.find( _pEntry->GetElement() );
+ if ( _rModelMap.end() != aPos )
+ { // there is a shape for this model ....
+ bIsMarked = _pView->IsObjMarked( aPos->second );
+ if ( !bIsMarked )
+ {
+ // IsObjMarked does not step down grouped objects, so the sal_False we
+ // have is not really reliable (while a sal_True would have been)
+ // Okay, travel the mark list, and see if there is a group marked, and our shape
+ // is a part of this group
+ sal_uInt32 nMarked = _pView->GetMarkedObjectList().GetMarkCount();
+ for ( sal_uInt32 i = 0; (i<nMarked ) && !bIsMarked; ++i )
+ {
+ SdrMark* pMark = _pView->GetMarkedObjectList().GetMark( i );
+ SdrObject* pObj = pMark ? pMark->GetMarkedSdrObj() : NULL;
+ if ( pObj && pObj->IsGroupObject() )
+ { // the i-th marked shape is a group shape
+ SdrObjListIter aIter( *pObj );
+ while ( aIter.IsMore() )
+ {
+ if ( aIter.Next() == aPos->second )
+ {
+ bIsMarked = sal_True;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return bIsMarked;
+ }
+
+ //========================================================================
+ // class NavigatorTree
+ //========================================================================
+
+ //------------------------------------------------------------------------
+ NavigatorTree::NavigatorTree( const Reference< XMultiServiceFactory >& _xORB,
+ Window* pParent )
+ :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL ) // #100258# OJ WB_HSCROLL added
+ ,m_aControlExchange(this)
+ ,m_xORB(_xORB)
+ ,m_pNavModel( NULL )
+ ,m_pRootEntry(NULL)
+ ,m_pEditEntry(NULL)
+ ,nEditEvent(0)
+ ,m_sdiState(SDI_DIRTY)
+ ,m_aTimerTriggered(-1,-1)
+ ,m_aDropActionType( DA_SCROLLUP )
+ ,m_nSelectLock(0)
+ ,m_nFormsSelected(0)
+ ,m_nControlsSelected(0)
+ ,m_nHiddenControls(0)
+ ,m_aTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
+ ,m_bDragDataDirty(sal_False)
+ ,m_bPrevSelectionMixed(sal_False)
+ ,m_bMarkingObjects(sal_False)
+ ,m_bRootSelected(sal_False)
+ ,m_bInitialUpdate(sal_True)
+ ,m_bKeyboardCut( sal_False )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NavigatorTree" );
+ SetHelpId( HID_FORM_NAVIGATOR );
+
+ m_aNavigatorImages = ImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
+
+ SetNodeBitmaps(
+ m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
+ m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
+ );
+
+ SetDragDropMode(0xFFFF);
+ EnableInplaceEditing( sal_True );
+ SetSelectionMode(MULTIPLE_SELECTION);
+
+ m_pNavModel = new NavigatorTreeModel( m_aNavigatorImages );
+ Clear();
+
+ StartListening( *m_pNavModel );
+
+ m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer));
+
+ m_aSynchronizeTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnSynchronizeTimer));
+ SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
+ SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
+ }
+
+ //------------------------------------------------------------------------
+ NavigatorTree::~NavigatorTree()
+ {
+ if( nEditEvent )
+ Application::RemoveUserEvent( nEditEvent );
+
+ if (m_aSynchronizeTimer.IsActive())
+ m_aSynchronizeTimer.Stop();
+
+ DBG_ASSERT(GetNavModel() != NULL, "NavigatorTree::~NavigatorTree : unerwartet : kein ExplorerModel");
+ EndListening( *m_pNavModel );
+ Clear();
+ delete m_pNavModel;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::Clear()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Clear" );
+ m_pNavModel->Clear();
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::UpdateContent( FmFormShell* pFormShell )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::UpdateContent" );
+ if (m_bInitialUpdate)
+ {
+ GrabFocus();
+ m_bInitialUpdate = sal_False;
+ }
+
+ FmFormShell* pOldShell = GetNavModel()->GetFormShell();
+ FmFormPage* pOldPage = GetNavModel()->GetFormPage();
+ FmFormPage* pNewPage = pFormShell ? pFormShell->GetCurPage() : NULL;
+
+ if ((pOldShell != pFormShell) || (pOldPage != pNewPage))
+ {
+ // neue Shell, waehrend ich gerade editiere ?
+ if (IsEditingActive())
+ CancelTextEditing();
+
+ m_bDragDataDirty = sal_True; // sicherheitshalber, auch wenn ich gar nicht dragge
+ }
+ GetNavModel()->UpdateContent( pFormShell );
+
+ // wenn es eine Form gibt, die Root expandieren
+ if (m_pRootEntry && !IsExpanded(m_pRootEntry))
+ Expand(m_pRootEntry);
+ // wenn es GENAU eine Form gibt, auch diese expandieren
+ if (m_pRootEntry)
+ {
+ SvLBoxEntry* pFirst = FirstChild(m_pRootEntry);
+ if (pFirst && !NextSibling(pFirst))
+ Expand(pFirst);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ sal_Bool NavigatorTree::implAllowExchange( sal_Int8 _nAction, sal_Bool* _pHasNonHidden )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAllowExchange" );
+ SvLBoxEntry* pCurEntry = GetCurEntry();
+ if (!pCurEntry)
+ return sal_False;
+
+ // die Informationen fuer das AcceptDrop und ExecuteDrop
+ CollectSelectionData(SDI_ALL);
+ if (!m_arrCurrentSelection.Count())
+ // nothing to do
+ return sal_False;
+
+ // testen, ob es sich vielleicht ausschliesslich um hidden controls handelt (dann koennte ich pCtrlExch noch ein
+ // zusaetzliches Format geben)
+ sal_Bool bHasNonHidden = sal_False;
+ for (sal_Int32 i=0; i<m_arrCurrentSelection.Count(); i++)
+ {
+ FmEntryData* pCurrent = static_cast< FmEntryData* >( m_arrCurrentSelection[(sal_uInt16)i]->GetUserData() );
+ if ( IsHiddenControl( pCurrent ) )
+ continue;
+ bHasNonHidden = sal_True;
+ break;
+ }
+
+ if ( bHasNonHidden && ( 0 == ( _nAction & DND_ACTION_MOVE ) ) )
+ // non-hidden controls need to be moved
+ return sal_False;
+
+ if ( _pHasNonHidden )
+ *_pHasNonHidden = bHasNonHidden;
+
+ return sal_True;
+ }
+
+ //------------------------------------------------------------------------------
+ sal_Bool NavigatorTree::implPrepareExchange( sal_Int8 _nAction )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implPrepareExchange" );
+ sal_Int32 i;
+
+ EndSelection();
+
+ sal_Bool bHasNonHidden = sal_False;
+ if ( !implAllowExchange( _nAction, &bHasNonHidden ) )
+ return sal_False;
+
+ m_aControlExchange.prepareDrag();
+ m_aControlExchange->setFocusEntry( GetCurEntry() );
+
+ for ( i = 0; i < m_arrCurrentSelection.Count(); ++i )
+ m_aControlExchange->addSelectedEntry(m_arrCurrentSelection[(sal_uInt16)i]);
+
+ m_aControlExchange->setFormsRoot( GetNavModel()->GetFormPage()->GetForms() );
+ m_aControlExchange->buildPathFormat( this, m_pRootEntry );
+
+ if (!bHasNonHidden)
+ {
+ // eine entsprechende Sequenz aufbauen
+ Sequence< Reference< XInterface > > seqIFaces(m_arrCurrentSelection.Count());
+ Reference< XInterface >* pArray = seqIFaces.getArray();
+ for (i=0; i<m_arrCurrentSelection.Count(); ++i, ++pArray)
+ *pArray = static_cast< FmEntryData* >( m_arrCurrentSelection[(sal_uInt16)i]->GetUserData() )->GetElement();
+
+ // und das neue Format
+ m_aControlExchange->addHiddenControlsFormat(seqIFaces);
+ }
+
+ m_bDragDataDirty = sal_False;
+ return sal_True;
+ }
+
+ //------------------------------------------------------------------------------
+ void NavigatorTree::StartDrag( sal_Int8 /*nAction*/, const ::Point& /*rPosPixel*/ )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::StartDrag" );
+ EndSelection();
+
+ if ( !implPrepareExchange( DND_ACTION_COPYMOVE ) )
+ // nothing to do or something went wrong
+ return;
+
+ // jetzt haben wir alle in der aktuelle Situation moeglichen Formate eingesammelt, es kann also losgehen ...
+ m_aControlExchange.startDrag( DND_ACTION_COPYMOVE );
+ }
+
+ //------------------------------------------------------------------------------
+ void NavigatorTree::Command( const CommandEvent& rEvt )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Command" );
+ sal_Bool bHandled = sal_False;
+ switch( rEvt.GetCommand() )
+ {
+ case COMMAND_CONTEXTMENU:
+ {
+ // die Stelle, an der geklickt wurde
+ ::Point ptWhere;
+ if (rEvt.IsMouseEvent())
+ {
+ ptWhere = rEvt.GetMousePosPixel();
+ SvLBoxEntry* ptClickedOn = GetEntry(ptWhere);
+ if (ptClickedOn == NULL)
+ break;
+ if ( !IsSelected(ptClickedOn) )
+ {
+ SelectAll(sal_False);
+ Select(ptClickedOn, sal_True);
+ SetCurEntry(ptClickedOn);
+ }
+ }
+ else
+ {
+ if (m_arrCurrentSelection.Count() == 0) // kann nur bei Kontextmenue ueber Tastatur passieren
+ break;
+
+ SvLBoxEntry* pCurrent = GetCurEntry();
+ if (!pCurrent)
+ break;
+ ptWhere = GetEntryPosition(pCurrent);
+ }
+
+ // meine Selektionsdaten auf den aktuellen Stand
+ CollectSelectionData(SDI_ALL);
+
+ // wenn mindestens ein Nicht-Root-Eintrag selektiert ist und die Root auch, dann nehme ich letztere aus der Selektion
+ // fix wieder raus
+ if ( (m_arrCurrentSelection.Count() > 1) && m_bRootSelected )
+ {
+ Select( m_pRootEntry, sal_False );
+ SetCursor( m_arrCurrentSelection.GetObject(0), sal_True);
+ }
+ sal_Bool bSingleSelection = (m_arrCurrentSelection.Count() == 1);
+
+
+ DBG_ASSERT( (m_arrCurrentSelection.Count() > 0) || m_bRootSelected, "keine Eintraege selektiert" );
+ // solte nicht passieren, da ich oben bei der IsSelected-Abfrage auf jeden Fall einen selektiert haette,
+ // wenn das vorher nicht der Fall gewesen waere
+
+
+ // das Menue zusammenbasteln
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
+ if( pFormShell && pFormModel )
+ {
+ PopupMenu aContextMenu(SVX_RES(RID_FMEXPLORER_POPUPMENU));
+ PopupMenu* pSubMenuNew = aContextMenu.GetPopupMenu( SID_FM_NEW );
+
+ // das 'Neu'-Untermenue gibt es nur, wenn genau die Root oder genau ein Formular selektiert sind
+ aContextMenu.EnableItem( SID_FM_NEW, bSingleSelection && (m_nFormsSelected || m_bRootSelected) );
+
+ // 'Neu'\'Formular' unter genau den selben Bedingungen
+ pSubMenuNew->EnableItem( SID_FM_NEW_FORM, bSingleSelection && (m_nFormsSelected || m_bRootSelected) );
+ pSubMenuNew->SetItemImage(SID_FM_NEW_FORM, m_aNavigatorImages.GetImage(RID_SVXIMG_FORM));
+ pSubMenuNew->SetItemImage(SID_FM_NEW_HIDDEN, m_aNavigatorImages.GetImage(RID_SVXIMG_HIDDEN));
+
+ // 'Neu'\'verstecktes...', wenn genau ein Formular selektiert ist
+ pSubMenuNew->EnableItem( SID_FM_NEW_HIDDEN, bSingleSelection && m_nFormsSelected );
+
+ // 'Delete': everything which is not root can be removed
+ aContextMenu.EnableItem( SID_FM_DELETE, !m_bRootSelected );
+
+ // 'Cut', 'Copy' and 'Paste'
+ aContextMenu.EnableItem( SID_CUT, !m_bRootSelected && implAllowExchange( DND_ACTION_MOVE ) );
+ aContextMenu.EnableItem( SID_COPY, !m_bRootSelected && implAllowExchange( DND_ACTION_COPY ) );
+ aContextMenu.EnableItem( SID_PASTE, implAcceptPaste( ) );
+
+ // der TabDialog, wenn es genau ein Formular ist ...
+ aContextMenu.EnableItem( SID_FM_TAB_DIALOG, bSingleSelection && m_nFormsSelected );
+
+ // in XML forms, we don't allow for the properties of a form
+ // #i36484# / 2004-11-04 /- fs@openoffice.org
+ if ( pFormShell->GetImpl()->isEnhancedForm() && !m_nControlsSelected )
+ aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) );
+
+ // if the property browser is already open, we don't allow for the properties, too
+ if( pFormShell->GetImpl()->IsPropBrwOpen() )
+ aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) );
+ // and finally, if there's a mixed selection of forms and controls, disable the entry, too
+ else
+ aContextMenu.EnableItem( SID_FM_SHOW_PROPERTY_BROWSER,
+ (m_nControlsSelected && !m_nFormsSelected) || (!m_nControlsSelected && m_nFormsSelected) );
+
+ // Umbenennen gdw wenn ein Element und nicht die Root
+ aContextMenu.EnableItem( SID_FM_RENAME_OBJECT, bSingleSelection && !m_bRootSelected );
+
+ // der Reandonly-Eintrag ist nur auf der Root erlaubt
+ aContextMenu.EnableItem( SID_FM_OPEN_READONLY, m_bRootSelected );
+ // the same for automatic control focus
+ aContextMenu.EnableItem( SID_FM_AUTOCONTROLFOCUS, m_bRootSelected );
+
+ // die ConvertTo-Slots sind enabled, wenn genau ein Control selektiert ist, der
+ // dem Control entsprechende Slot ist disabled
+ if (!m_bRootSelected && !m_nFormsSelected && (m_nControlsSelected == 1))
+ {
+ aContextMenu.SetPopupMenu( SID_FM_CHANGECONTROLTYPE, FmXFormShell::GetConversionMenu() );
+#if OSL_DEBUG_LEVEL > 0
+ FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData());
+ OSL_ENSURE( pFormShell->GetImpl()->isSolelySelected( pCurrent->GetFormComponent() ),
+ "NavigatorTree::Command: inconsistency between the navigator selection, and the selection as the shell knows it!" );
+#endif
+
+ pFormShell->GetImpl()->checkControlConversionSlotsForCurrentSelection( *aContextMenu.GetPopupMenu( SID_FM_CHANGECONTROLTYPE ) );
+ }
+ else
+ aContextMenu.EnableItem( SID_FM_CHANGECONTROLTYPE, sal_False );
+
+ // jetzt alles, was disabled wurde, wech
+ aContextMenu.RemoveDisabledEntries(sal_True, sal_True);
+ //////////////////////////////////////////////////////////
+ // OpenReadOnly setzen
+
+ aContextMenu.CheckItem( SID_FM_OPEN_READONLY, pFormModel->GetOpenInDesignMode() );
+ aContextMenu.CheckItem( SID_FM_AUTOCONTROLFOCUS, pFormModel->GetAutoControlFocus() );
+
+ sal_uInt16 nSlotId = aContextMenu.Execute( this, ptWhere );
+ switch( nSlotId )
+ {
+ case SID_FM_NEW_FORM:
+ {
+ XubString aStr(SVX_RES(RID_STR_FORM));
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+
+ pFormModel->BegUndo(aUndoStr);
+ // der Slot war nur verfuegbar, wenn es genau einen selektierten Eintrag gibt und dieser die Root
+ // oder ein Formular ist
+ NewForm( m_arrCurrentSelection.GetObject(0) );
+ pFormModel->EndUndo();
+
+ } break;
+ case SID_FM_NEW_HIDDEN:
+ {
+ XubString aStr(SVX_RES(RID_STR_CONTROL));
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+
+ pFormModel->BegUndo(aUndoStr);
+ // dieser Slot war guletig bei (genau) einem selektierten Formular
+ rtl::OUString fControlName = FM_COMPONENT_HIDDEN;
+ NewControl( fControlName, m_arrCurrentSelection.GetObject(0) );
+ pFormModel->EndUndo();
+
+ } break;
+
+ case SID_CUT:
+ doCut();
+ break;
+
+ case SID_COPY:
+ doCopy();
+ break;
+
+ case SID_PASTE:
+ doPaste();
+ break;
+
+ case SID_FM_DELETE:
+ {
+ DeleteSelection();
+ }
+ break;
+ case SID_FM_TAB_DIALOG:
+ {
+ // dieser Slot galt bei genau einem selektierten Formular
+ SvLBoxEntry* pSelectedForm = m_arrCurrentSelection.GetObject(0);
+ DBG_ASSERT( IsFormEntry(pSelectedForm), "NavigatorTree::Command: Dieser Eintrag muss ein FormEntry sein." );
+
+ FmFormData* pFormData = (FmFormData*)pSelectedForm->GetUserData();
+ Reference< XForm > xForm( pFormData->GetFormIface());
+
+ Reference< XTabControllerModel > xTabController(xForm, UNO_QUERY);
+ if( !xTabController.is() )
+ break;
+ GetNavModel()->GetFormShell()->GetImpl()->ExecuteTabOrderDialog( xTabController );
+ }
+ break;
+
+ case SID_FM_SHOW_PROPERTY_BROWSER:
+ {
+ ShowSelectionProperties(sal_True);
+ }
+ break;
+ case SID_FM_RENAME_OBJECT:
+ {
+ // das war bei genau einem Nicht-Root-Eintrag erlaubt
+ EditEntry( m_arrCurrentSelection.GetObject(0) );
+ }
+ break;
+ case SID_FM_OPEN_READONLY:
+ {
+ pFormModel->SetOpenInDesignMode( !pFormModel->GetOpenInDesignMode() );
+ pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY);
+ }
+ break;
+ case SID_FM_AUTOCONTROLFOCUS:
+ {
+ pFormModel->SetAutoControlFocus( !pFormModel->GetAutoControlFocus() );
+ pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS);
+ }
+ break;
+ default:
+ if (pFormShell->GetImpl()->isControlConversionSlot(nSlotId))
+ {
+ FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData());
+ if ( pFormShell->GetImpl()->executeControlConversionSlot( pCurrent->GetFormComponent(), nSlotId ) )
+ ShowSelectionProperties();
+ }
+ }
+ }
+ bHandled = sal_True;
+ } break;
+ }
+
+ if (!bHandled)
+ SvTreeListBox::Command( rEvt );
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::IsDeleteAllowed()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsDeleteAllowed" );
+ //////////////////////////////////////////////////////////////////////
+ // Haben wir eine Form...
+ SvLBoxEntry* pCurEntry = GetCurEntry();
+ sal_uInt32 nCurEntryPos = GetModel()->GetAbsPos( pCurEntry );
+
+ if( nCurEntryPos==0 ) // Root kann nicht geloescht werden
+ return sal_False;
+ else
+ return IsFormEntry(pCurEntry) || IsFormComponentEntry(pCurEntry);
+ }
+
+ //------------------------------------------------------------------------
+ SvLBoxEntry* NavigatorTree::FindEntry( FmEntryData* pEntryData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::FindEntry" );
+ if( !pEntryData ) return NULL;
+ SvLBoxEntry* pCurEntry = First();
+ FmEntryData* pCurEntryData;
+ while( pCurEntry )
+ {
+ pCurEntryData = (FmEntryData*)pCurEntry->GetUserData();
+ if( pCurEntryData && pCurEntryData->IsEqualWithoutChilds(pEntryData) )
+ return pCurEntry;
+
+ pCurEntry = Next( pCurEntry );
+ }
+
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Notify" );
+ if( rHint.ISA(FmNavRemovedHint) )
+ {
+ FmNavRemovedHint* pRemovedHint = (FmNavRemovedHint*)&rHint;
+ FmEntryData* pEntryData = pRemovedHint->GetEntryData();
+ Remove( pEntryData );
+ }
+
+ else if( rHint.ISA(FmNavInsertedHint) )
+ {
+ FmNavInsertedHint* pInsertedHint = (FmNavInsertedHint*)&rHint;
+ FmEntryData* pEntryData = pInsertedHint->GetEntryData();
+ sal_uInt32 nRelPos = pInsertedHint->GetRelPos();
+ Insert( pEntryData, nRelPos );
+ }
+
+ else if( rHint.ISA(FmNavModelReplacedHint) )
+ {
+ FmEntryData* pData = ((FmNavModelReplacedHint*)&rHint)->GetEntryData();
+ SvLBoxEntry* pEntry = FindEntry( pData );
+ if (pEntry)
+ { // das Image neu setzen
+ SetCollapsedEntryBmp( pEntry, pData->GetNormalImage() );
+ SetExpandedEntryBmp( pEntry, pData->GetNormalImage() );
+ }
+ }
+
+ else if( rHint.ISA(FmNavNameChangedHint) )
+ {
+ FmNavNameChangedHint* pNameChangedHint = (FmNavNameChangedHint*)&rHint;
+ SvLBoxEntry* pEntry = FindEntry( pNameChangedHint->GetEntryData() );
+ SetEntryText( pEntry, pNameChangedHint->GetNewName() );
+ }
+
+ else if( rHint.ISA(FmNavClearedHint) )
+ {
+ SvTreeListBox::Clear();
+
+ //////////////////////////////////////////////////////////////////////
+ // Default-Eintrag "Formulare"
+ Image aRootImage( m_aNavigatorImages.GetImage( RID_SVXIMG_FORMS ) );
+ m_pRootEntry = InsertEntry( SVX_RES(RID_STR_FORMS), aRootImage, aRootImage,
+ NULL, sal_False, 0, NULL );
+ }
+ else if (!m_bMarkingObjects && rHint.ISA(FmNavRequestSelectHint))
+ { // wenn m_bMarkingObjects sal_True ist, markiere ich gerade selber Objekte, und da der ganze Mechanismus dahinter synchron ist,
+ // ist das genau der Hint, der durch mein Markieren ausgeloest wird, also kann ich ihn ignorieren
+ FmNavRequestSelectHint* pershHint = (FmNavRequestSelectHint*)&rHint;
+ FmEntryDataArray& arredToSelect = pershHint->GetItems();
+ SynchronizeSelection(arredToSelect);
+
+ if (pershHint->IsMixedSelection())
+ // in diesem Fall habe ich alles deselektiert, obwohl die View u.U. eine gemischte Markierung hatte
+ // ich muss also im naechsten Select den Navigator an die View anpassen
+ m_bPrevSelectionMixed = sal_True;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ SvLBoxEntry* NavigatorTree::Insert( FmEntryData* pEntryData, ULONG nRelPos )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Insert" );
+ //////////////////////////////////////////////////////////////////////
+ // Aktuellen Eintrag einfuegen
+ SvLBoxEntry* pParentEntry = FindEntry( pEntryData->GetParent() );
+ SvLBoxEntry* pNewEntry;
+
+ if( !pParentEntry )
+ pNewEntry = InsertEntry( pEntryData->GetText(),
+ pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
+ m_pRootEntry, sal_False, nRelPos, pEntryData );
+
+ else
+ pNewEntry = InsertEntry( pEntryData->GetText(),
+ pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
+ pParentEntry, sal_False, nRelPos, pEntryData );
+
+ //////////////////////////////////////////////////////////////////////
+ // Wenn Root-Eintrag Root expandieren
+ if( !pParentEntry )
+ Expand( m_pRootEntry );
+
+ //////////////////////////////////////////////////////////////////////
+ // Childs einfuegen
+ FmEntryDataList* pChildList = pEntryData->GetChildList();
+ size_t nChildCount = pChildList->size();
+ FmEntryData* pChildData;
+ for( size_t i = 0; i < nChildCount; i++ )
+ {
+ pChildData = pChildList->at( i );
+ Insert( pChildData, LIST_APPEND );
+ }
+
+ return pNewEntry;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::Remove( FmEntryData* pEntryData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Remove" );
+ if( !pEntryData )
+ return;
+
+ // der Entry zu den Daten
+ SvLBoxEntry* pEntry = FindEntry( pEntryData );
+ if (!pEntry)
+ return;
+
+ // Eintrag aus TreeListBox entfernen
+ // ich darf das Select, das ich ausloese, nicht behandeln :
+ // Select aendert die MarkList der View, wenn das gerade auch jemand anders macht und dabei ein Remove
+ // triggert, haben wir mit ziemlicher Sicherheit ein Problem - Paradebeispiel war das Gruppieren von Controls mit
+ // offenem Navigator ...)
+ LockSelectionHandling();
+
+ // ein kleines Problem : ich merke mir meine selektierten Daten, wenn mir jetzt jemand einen selektierten Eintrag
+ // unter dem Hintern wegschiesst, werde ich inkonsistent ... was schlecht waere
+ Select(pEntry, sal_False);
+
+ // beim eigentlichen Entfernen kann die Selection geaendert werden, da ich aber das SelectionHandling abgeschaltet
+ // habe, muss ich mich hinterher darum kuemmern
+ ULONG nExpectedSelectionCount = GetSelectionCount();
+
+ if( pEntry )
+ GetModel()->Remove( pEntry );
+
+ if (nExpectedSelectionCount != GetSelectionCount())
+ SynchronizeSelection();
+
+ // und standardmaessig behandle ich das Select natuerlich
+ UnlockSelectionHandling();
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::IsFormEntry( SvLBoxEntry* pEntry )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsFormEntry" );
+ FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData();
+ return !pEntryData || pEntryData->ISA(FmFormData);
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::IsFormComponentEntry( SvLBoxEntry* pEntry )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsFormComponentEntry" );
+ FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData();
+ return pEntryData && pEntryData->ISA(FmControlData);
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::implAcceptPaste( )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptPaste" );
+ SvLBoxEntry* pFirstSelected = FirstSelected();
+ if ( !pFirstSelected || NextSelected( pFirstSelected ) )
+ // no selected entry, or at least two selected entries
+ return sal_False;
+
+ // get the clipboard
+ TransferableDataHelper aClipboardContent( TransferableDataHelper::CreateFromSystemClipboard( this ) );
+
+ sal_Int8 nAction = m_aControlExchange.isClipboardOwner() && doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY;
+ return ( nAction == implAcceptDataTransfer( aClipboardContent.GetDataFlavorExVector(), nAction, pFirstSelected, sal_False ) );
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const ::Point& _rDropPos, sal_Bool _bDnD )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptDataTransfer" );
+ return implAcceptDataTransfer( _rFlavors, _nAction, GetEntry( _rDropPos ), _bDnD );
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, SvLBoxEntry* _pTargetEntry, sal_Bool _bDnD )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptDataTransfer" );
+ // no target -> no drop
+ if (!_pTargetEntry)
+ return DND_ACTION_NONE;
+
+ // format check
+ sal_Bool bHasDefControlFormat = OControlExchange::hasFieldExchangeFormat( _rFlavors );
+ sal_Bool bHasControlPathFormat = OControlExchange::hasControlPathFormat( _rFlavors );
+ sal_Bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( _rFlavors );
+ if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat)
+ return DND_ACTION_NONE;
+
+ sal_Bool bSelfSource = _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner();
+
+ if ( bHasHiddenControlsFormat )
+ { // bHasHiddenControlsFormat means that only hidden controls are part of the data
+
+ // hidden controls can be copied to a form only
+ if ( !_pTargetEntry || ( _pTargetEntry == m_pRootEntry ) || !IsFormEntry( _pTargetEntry ) )
+ return DND_ACTION_NONE;
+
+ return bSelfSource ? ( DND_ACTION_COPYMOVE & _nAction ) : DND_ACTION_COPY;
+ }
+
+ if ( !bSelfSource )
+ {
+ // DnD or CnP crossing navigator boundaries
+ // The main problem here is that the current API does not allow us to sneak into the content which
+ // is to be inserted. So we have to allow it for the moment, but maybe reject later on (in the real drop).
+
+ // TODO: this smart behaviour later on ... at the moment, we disallow data transfer crossing navigator
+ // boundaries.
+
+ return DND_ACTION_NONE;
+ }
+
+ DBG_ASSERT( _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner(),
+ "NavigatorTree::implAcceptDataTransfer: here only with source=dest!" );
+ // somebody changed the logic of this method ...
+
+ // from here on, I can work with m_aControlExchange instead of _rData!
+
+ sal_Bool bForeignCollection = m_aControlExchange->getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
+ if ( bForeignCollection )
+ {
+ // crossing shell/page boundaries, we can exchange hidden controls only
+ // But if we survived the checks above, we do not have hidden controls.
+ // -> no data transfer
+ DBG_ASSERT( !bHasHiddenControlsFormat, "NavigatorTree::implAcceptDataTransfer: still hidden controls format!" );
+ // somebody changed the logic of this method ...
+
+ return DND_ACTION_COPY;
+ }
+
+ if (DND_ACTION_MOVE != _nAction) // 'normal' controls within a shell are moved only (never copied)
+ return DND_ACTION_NONE;
+
+ if ( m_bDragDataDirty || !bHasDefControlFormat )
+ {
+ if (!bHasControlPathFormat)
+ // ich befinde mich zwar in der Shell/Page, aus der die Controls stammen, habe aber kein Format, das den stattgefundenen
+ // Shell-Wechsel ueberlebt hat (SVX_FM_CONTROLS_AS_PATH)
+ return DND_ACTION_NONE;
+
+ // da die Shell waehrend des Draggens umgeschaltet wude, muss ich die Liste des ExchangeObjektes wieder neu aufbauen
+ // (dort stehen SvLBoxEntries drin, und die sind bei der Umschaltung floeten gegangen)
+ m_aControlExchange->buildListFromPath(this, m_pRootEntry);
+ m_bDragDataDirty = sal_False;
+ }
+
+ // die Liste der gedroppten Eintraege aus dem DragServer
+ const ListBoxEntrySet& aDropped = m_aControlExchange->selected();
+ DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implAcceptDataTransfer: keine Eintraege !");
+
+ sal_Bool bDropTargetIsComponent = IsFormComponentEntry( _pTargetEntry );
+ //SvLBoxEntry* pDropTargetParent = GetParent( _pTargetEntry );
+
+ // conditions to disallow the drop
+ // 0) the root entry is part of the list (can't DnD the root!)
+ // 1) one of the draged entries is to be dropped onto it's own parent
+ // 2) - " - is to be dropped onto itself
+ // 3) - " - is a Form and to be dropped onto one of it's descendants
+ // 4) one of the entries is a control and to be dropped onto the root
+ // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling
+ // means moving the control)
+
+ // collect the ancestors of the drop targte (speeds up 3)
+ SvLBoxEntrySortedArray arrDropAnchestors;
+ SvLBoxEntry* pLoop = _pTargetEntry;
+ while (pLoop)
+ {
+ arrDropAnchestors.Insert(pLoop);
+ pLoop = GetParent(pLoop);
+ }
+
+ for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
+ dropped != aDropped.end();
+ ++dropped
+ )
+ {
+ SvLBoxEntry* pCurrent = *dropped;
+ SvLBoxEntry* pCurrentParent = GetParent(pCurrent);
+
+ // test for 0)
+ if (pCurrent == m_pRootEntry)
+ return DND_ACTION_NONE;
+
+ // test for 1)
+ if ( _pTargetEntry == pCurrentParent )
+ return DND_ACTION_NONE;
+
+ // test for 2)
+ if (pCurrent == _pTargetEntry)
+ return DND_ACTION_NONE;
+
+ // test for 5)
+ // if ( bDropTargetIsComponent && (pDropTargetParent != pCurrentParent) )
+ if ( bDropTargetIsComponent ) // TODO : die obige Zeile wieder rein, dann muss aber ExecuteDrop das Vertauschen auch beherrschen
+ return DND_ACTION_NONE;
+
+ // test for 3)
+ if ( IsFormEntry(pCurrent) )
+ {
+ sal_uInt16 nPosition;
+ if ( arrDropAnchestors.Seek_Entry(pCurrent, &nPosition) )
+ return DND_ACTION_NONE;
+ } else if ( IsFormComponentEntry(pCurrent) )
+ {
+ // test for 4)
+ if (_pTargetEntry == m_pRootEntry)
+ return DND_ACTION_NONE;
+ }
+ }
+
+ return DND_ACTION_MOVE;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& rEvt )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::AcceptDrop" );
+ ::Point aDropPos = rEvt.maPosPixel;
+
+ // kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen)
+ if (rEvt.mbLeaving)
+ {
+ if (m_aDropActionTimer.IsActive())
+ m_aDropActionTimer.Stop();
+ } else
+ {
+ sal_Bool bNeedTrigger = sal_False;
+ // auf dem ersten Eintrag ?
+ if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
+ {
+ m_aDropActionType = DA_SCROLLUP;
+ bNeedTrigger = sal_True;
+ } else
+ // auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig
+ // abschliessen wuerde) ?
+ if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
+ {
+ m_aDropActionType = DA_SCROLLDOWN;
+ bNeedTrigger = sal_True;
+ } else
+ { // auf einem Entry mit Childs, der nicht aufgeklappt ist ?
+ SvLBoxEntry* pDropppedOn = GetEntry(aDropPos);
+ if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
+ {
+ // -> aufklappen
+ m_aDropActionType = DA_EXPANDNODE;
+ bNeedTrigger = sal_True;
+ }
+ }
+
+ if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
+ {
+ // neu anfangen zu zaehlen
+ m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
+ // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat
+ m_aTimerTriggered = aDropPos;
+ // und den Timer los
+ if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
+ {
+ m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
+ m_aDropActionTimer.Start();
+ }
+ } else if (!bNeedTrigger)
+ m_aDropActionTimer.Stop();
+ }
+
+ return implAcceptDataTransfer( GetDataFlavorExVector(), rEvt.mnAction, aDropPos, sal_True );
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const ::Point& _rDropPos, sal_Bool _bDnD )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implExecuteDataTransfer" );
+ return implExecuteDataTransfer( _rData, _nAction, GetEntry( _rDropPos ), _bDnD );
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, SvLBoxEntry* _pTargetEntry, sal_Bool _bDnD )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implExecuteDataTransfer" );
+ const DataFlavorExVector& rDataFlavors = _rData.GetDataFlavorExVector();
+
+ if ( DND_ACTION_NONE == implAcceptDataTransfer( rDataFlavors, _nAction, _pTargetEntry, _bDnD ) )
+ // under some platforms, it may happen that ExecuteDrop is called though AcceptDrop returned DND_ACTION_NONE
+ return DND_ACTION_NONE;
+
+ // ware schlecht, wenn nach dem Droppen noch gescrollt wird ...
+ if (m_aDropActionTimer.IsActive())
+ m_aDropActionTimer.Stop();
+
+ if (!_pTargetEntry)
+ // no target -> no drop
+ return DND_ACTION_NONE;
+
+ // format checks
+#ifdef DBG_UTIL
+ sal_Bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( rDataFlavors );
+ sal_Bool bForeignCollection = _rData.getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
+ DBG_ASSERT(!bForeignCollection || bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: invalid format (AcceptDrop shouldn't have let this pass) !");
+ DBG_ASSERT(bForeignCollection || !m_bDragDataDirty, "NavigatorTree::implExecuteDataTransfer: invalid state (shell changed since last exchange resync) !");
+ // das sollte in AcceptDrop erledigt worden sein : dort wird in _rData die Liste der Controls aufgebaut und m_bDragDataDirty
+ // zurueckgesetzt
+#endif
+
+ if ( DND_ACTION_COPY == _nAction )
+ { // bHasHiddenControlsFormat means that only hidden controls are part of the data
+ DBG_ASSERT( bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: copy allowed for hidden controls only!" );
+ DBG_ASSERT( _pTargetEntry && ( _pTargetEntry != m_pRootEntry ) && IsFormEntry( _pTargetEntry ),
+ "NavigatorTree::implExecuteDataTransfer: should not be here!" );
+ // implAcceptDataTransfer should have caught both cases
+
+ DBG_ASSERT(bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: only copying of hidden controls is supported !");
+ // das sollte das AcceptDrop abgefangen haben
+
+ // da ich gleich die Zielobjekte alle selektieren will (und nur die)
+ SelectAll(sal_False);
+
+ Sequence< Reference< XInterface > > aControls = _rData.hiddenControls();
+ sal_Int32 nCount = aControls.getLength();
+ const Reference< XInterface >* pControls = aControls.getConstArray();
+
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
+
+ // innerhalb eines Undo ...
+ if (pFormModel)
+ {
+ XubString aStr(SVX_RES(RID_STR_CONTROL));
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+ pFormModel->BegUndo(aUndoStr);
+ }
+
+ // die Conrtols kopieren
+ for (sal_Int32 i=0; i<nCount; ++i)
+ {
+ // neues Control anlegen
+ rtl::OUString fControlName = FM_COMPONENT_HIDDEN;
+ FmControlData* pNewControlData = NewControl( fControlName, _pTargetEntry, sal_False);
+ Reference< XPropertySet > xNewPropSet( pNewControlData->GetPropertySet() );
+
+ // und die Properties des alten in das neue kopieren
+ Reference< XPropertySet > xCurrent(pControls[i], UNO_QUERY);
+#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
+ // nur mal eben sehen, ob das Ding tatsaechlich ein hidden control ist
+ sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID));
+ OSL_ENSURE(nClassId == FormComponentType::HIDDENCONTROL, "NavigatorTree::implExecuteDataTransfer: invalid control in drop list !");
+ // wenn das SVX_FM_HIDDEN_CONTROLS-Format vorhanden ist, dann sollten wirklich nur hidden controls in der Sequenz
+ // stecken
+#endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL
+ Reference< XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo());
+ Sequence< Property> seqAllCurrentProps = xPropInfo->getProperties();
+ Property* pAllCurrentProps = seqAllCurrentProps.getArray();
+ for (sal_Int32 j=0; j<seqAllCurrentProps.getLength(); ++j)
+ {
+ ::rtl::OUString sCurrentProp = pAllCurrentProps[j].Name;
+ if (((pAllCurrentProps[j].Attributes & PropertyAttribute::READONLY) == 0) && (sCurrentProp != FM_PROP_NAME))
+ { // (read-only attribs werden natuerlich nicht gesetzt, dito der Name, den hat das NewControl schon eindeutig
+ // festgelegt)
+ xNewPropSet->setPropertyValue(sCurrentProp, xCurrent->getPropertyValue(sCurrentProp));
+ }
+ }
+
+ SvLBoxEntry* pToSelect = FindEntry(pNewControlData);
+ Select(pToSelect, sal_True);
+ if (i == 0)
+ SetCurEntry(pToSelect);
+ }
+
+ if (pFormModel)
+ pFormModel->EndUndo();
+
+ return _nAction;
+ }
+
+ if ( !OControlExchange::hasFieldExchangeFormat( _rData.GetDataFlavorExVector() ) )
+ {
+ // can't do anything without the internal format here ... usually happens when doing DnD or CnP
+ // over navigator boundaries
+ return DND_ACTION_NONE;
+ }
+
+ // some data for the target
+ sal_Bool bDropTargetIsForm = IsFormEntry(_pTargetEntry);
+ FmFormData* pTargetData = bDropTargetIsForm ? (FmFormData*)_pTargetEntry->GetUserData() : NULL;
+
+ DBG_ASSERT( DND_ACTION_COPY != _nAction, "NavigatorTree::implExecuteDataTransfer: somebody changed the logics!" );
+
+ // die Liste der gedraggten Eintraege
+ ListBoxEntrySet aDropped = _rData.selected();
+ DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implExecuteDataTransfer: no entries!");
+
+ // die Shell und das Model
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
+ if (!pFormModel)
+ return DND_ACTION_NONE;
+
+ // fuer's Undo
+ const bool bUndo = pFormModel->IsUndoEnabled();
+
+ if( bUndo )
+ {
+ XubString strUndoDescription(SVX_RES(RID_STR_UNDO_CONTAINER_REPLACE));
+ pFormModel->BegUndo(strUndoDescription);
+ }
+
+ // ich nehme vor dem Einfuegen eines Eintrages seine Selection raus, damit die Markierung dabei nicht flackert
+ // -> das Handeln des Select locken
+ LockSelectionHandling();
+
+ // jetzt durch alle gedroppten Eintraege ...
+ for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
+ dropped != aDropped.end();
+ ++dropped
+ )
+ {
+ // ein paar Daten zum aktuellen Element
+ SvLBoxEntry* pCurrent = *dropped;
+ DBG_ASSERT(pCurrent != NULL, "NavigatorTree::implExecuteDataTransfer: ungueltiger Eintrag");
+ DBG_ASSERT(GetParent(pCurrent) != NULL, "NavigatorTree::implExecuteDataTransfer: ungueltiger Eintrag");
+ // die Root darf nicht gedraggt werden
+
+ FmEntryData* pCurrentUserData = (FmEntryData*)pCurrent->GetUserData();
+
+ Reference< XChild > xCurrentChild(pCurrentUserData->GetChildIFace(), UNO_QUERY);
+ Reference< XIndexContainer > xContainer(xCurrentChild->getParent(), UNO_QUERY);
+
+ FmFormData* pCurrentParentUserData = (FmFormData*)pCurrentUserData->GetParent();
+ DBG_ASSERT(pCurrentParentUserData == NULL || pCurrentParentUserData->ISA(FmFormData), "NavigatorTree::implExecuteDataTransfer: ungueltiges Parent");
+
+ // beim Vater austragen
+ if (pCurrentParentUserData)
+ pCurrentParentUserData->GetChildList()->remove( pCurrentUserData );
+ else
+ GetNavModel()->GetRootList()->remove( pCurrentUserData );
+
+ // aus dem Container entfernen
+ sal_Int32 nIndex = getElementPos(Reference< XIndexAccess > (xContainer, UNO_QUERY), xCurrentChild);
+ GetNavModel()->m_pPropChangeList->Lock();
+ // die Undo-Action fuer das Rausnehmen
+ if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
+ {
+ pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Removed,
+ xContainer, xCurrentChild, nIndex));
+ }
+ else if( !GetNavModel()->m_pPropChangeList->CanUndo() )
+ {
+ FmUndoContainerAction::DisposeElement( xCurrentChild );
+ }
+
+ // Events mitkopieren
+ Reference< XEventAttacherManager > xManager(xContainer, UNO_QUERY);
+ Sequence< ScriptEventDescriptor > aEvts;
+
+ if (xManager.is() && nIndex >= 0)
+ aEvts = xManager->getScriptEvents(nIndex);
+ xContainer->removeByIndex(nIndex);
+
+ // die Selection raus
+ Select(pCurrent, sal_False);
+ // und weg
+ Remove(pCurrentUserData);
+
+ // die Stelle innerhalb des DropParents, an der ich die gedroppten Eintraege einfuegen muss
+ if (pTargetData)
+ xContainer = Reference< XIndexContainer > (pTargetData->GetElement(), UNO_QUERY);
+ else
+ xContainer = Reference< XIndexContainer > (GetNavModel()->GetForms(), UNO_QUERY);
+
+ // immer ganz hinten einfuegen
+ nIndex = xContainer->getCount();
+
+ // UndoAction fuer das Einfuegen
+ if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
+ pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Inserted,
+ xContainer, xCurrentChild, nIndex));
+
+ // einfuegen im neuen Container
+ if (pTargetData)
+ {
+ // es wird in eine Form eingefuegt, dann brauche ich eine FormComponent
+ xContainer->insertByIndex( nIndex,
+ makeAny( Reference< XFormComponent >( xCurrentChild, UNO_QUERY ) ) );
+ }
+ else
+ {
+ xContainer->insertByIndex( nIndex,
+ makeAny( Reference< XForm >( xCurrentChild, UNO_QUERY ) ) );
+ }
+
+ if (aEvts.getLength())
+ {
+ xManager = Reference< XEventAttacherManager > (xContainer, UNO_QUERY);
+ if (xManager.is())
+ xManager->registerScriptEvents(nIndex, aEvts);
+ }
+
+ GetNavModel()->m_pPropChangeList->UnLock();
+
+ // zuerst dem Eintrag das neue Parent
+ pCurrentUserData->SetParent(pTargetData);
+
+ // dann dem Parent das neue Child
+ if (pTargetData)
+ pTargetData->GetChildList()->insert( pCurrentUserData, nIndex );
+ else
+ GetNavModel()->GetRootList()->insert( pCurrentUserData, nIndex );
+
+ // dann bei mir selber bekanntgeben und neu selektieren
+ SvLBoxEntry* pNew = Insert( pCurrentUserData, nIndex );
+ if ( ( aDropped.begin() == dropped ) && pNew )
+ {
+ SvLBoxEntry* pParent = GetParent( pNew );
+ if ( pParent )
+ Expand( pParent );
+ }
+ }
+
+ UnlockSelectionHandling();
+
+ if( bUndo )
+ pFormModel->EndUndo();
+
+ // During the move, the markings of the underlying view did not change (because the view is not affected by the logical
+ // hierarchy of the form/control models. But my selection changed - which means I have to adjust it according to the
+ // view marks, again.
+ SynchronizeSelection();
+
+ // in addition, with the move of controls such things as "the current form" may have changed - force the shell
+ // to update itself accordingly
+ if( pFormShell && pFormShell->GetImpl() && pFormShell->GetFormView() )
+ pFormShell->GetImpl()->DetermineSelection( pFormShell->GetFormView()->GetMarkedObjectList() );
+
+ if ( m_aControlExchange.isClipboardOwner() && ( DND_ACTION_MOVE == _nAction ) )
+ m_aControlExchange->clear();
+
+ return _nAction;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& rEvt )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ExecuteDrop" );
+ sal_Int8 nResult( DND_ACTION_NONE );
+
+ if ( m_aControlExchange.isDragSource() )
+ nResult = implExecuteDataTransfer( *m_aControlExchange, rEvt.mnAction, rEvt.maPosPixel, sal_True );
+ else
+ {
+ OControlTransferData aDroppedData( rEvt.maDropEvent.Transferable );
+ nResult = implExecuteDataTransfer( aDroppedData, rEvt.mnAction, rEvt.maPosPixel, sal_True );
+ }
+
+ return nResult;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::doPaste()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doPaste" );
+ try
+ {
+ if ( m_aControlExchange.isClipboardOwner() )
+ {
+ implExecuteDataTransfer( *m_aControlExchange, doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY, FirstSelected(), sal_False );
+ }
+ else
+ {
+ // the clipboard content
+ Reference< XClipboard > xClipboard( GetClipboard() );
+ Reference< XTransferable > xTransferable;
+ if ( xClipboard.is() )
+ xTransferable = xClipboard->getContents();
+
+ OControlTransferData aClipboardContent( xTransferable );
+ implExecuteDataTransfer( aClipboardContent, DND_ACTION_COPY, FirstSelected(), sal_False );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "NavigatorTree::doPaste: caught an exception!" );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::doCopy()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doCopy" );
+ if ( implPrepareExchange( DND_ACTION_COPY ) )
+ {
+ m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
+ m_aControlExchange.copyToClipboard( );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::ModelHasRemoved( SvListEntry* _pEntry )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ModelHasRemoved" );
+ SvLBoxEntry* pTypedEntry = static_cast< SvLBoxEntry* >( _pEntry );
+ if ( doingKeyboardCut() )
+ m_aCutEntries.erase( pTypedEntry );
+
+ if ( m_aControlExchange.isDataExchangeActive() )
+ {
+ if ( 0 == m_aControlExchange->onEntryRemoved( pTypedEntry ) )
+ {
+ // last of the entries which we put into the clipboard has been deleted from the tree.
+ // Give up the clipboard ownership.
+ m_aControlExchange.clear();
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::doCut()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doCut" );
+ if ( implPrepareExchange( DND_ACTION_MOVE ) )
+ {
+ m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
+ m_aControlExchange.copyToClipboard( );
+ m_bKeyboardCut = sal_True;
+
+ // mark all the entries we just "cut" into the clipboard as "nearly moved"
+ for ( sal_Int32 i=0; i<m_arrCurrentSelection.Count(); ++i )
+ {
+ SvLBoxEntry* pEntry = m_arrCurrentSelection[ (sal_uInt16)i ];
+ if ( pEntry )
+ {
+ m_aCutEntries.insert( pEntry );
+ pEntry->SetFlags( pEntry->GetFlags() | SV_ENTRYFLAG_SEMITRANSPARENT );
+ InvalidateEntry( pEntry );
+ }
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::KeyInput(const ::KeyEvent& rKEvt)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::KeyInput" );
+ const KeyCode& rCode = rKEvt.GetKeyCode();
+
+ // delete?
+ if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE && !rKEvt.GetKeyCode().GetModifier())
+ {
+ DeleteSelection();
+ return;
+ }
+
+ // copy'n'paste?
+ switch ( rCode.GetFunction() )
+ {
+ case KEYFUNC_CUT:
+ doCut();
+ break;
+
+ case KEYFUNC_PASTE:
+ if ( implAcceptPaste() )
+ doPaste();
+ break;
+
+ case KEYFUNC_COPY:
+ doCopy();
+ break;
+
+ default:
+ break;
+ }
+
+ SvTreeListBox::KeyInput(rKEvt);
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::EditingEntry" );
+ if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
+ return sal_False;
+
+ return (pEntry && (pEntry->GetUserData() != NULL));
+ // die Wurzel, die ich nicht umbenennen darf, hat als UserData NULL
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::NewForm( SvLBoxEntry* pParentEntry )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NewForm" );
+ //////////////////////////////////////////////////////////////////////
+ // ParentFormData holen
+ if( !IsFormEntry(pParentEntry) )
+ return;
+
+ FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData();
+
+ //////////////////////////////////////////////////////////////////////
+ // Neue Form erzeugen
+ Reference< XForm > xNewForm(m_xORB->createInstance(FM_SUN_COMPONENT_FORM), UNO_QUERY);
+ if (!xNewForm.is())
+ return;
+
+ FmFormData* pNewFormData = new FmFormData( xNewForm, m_aNavigatorImages, pParentFormData );
+
+ //////////////////////////////////////////////////////////////////////
+ // Namen setzen
+ ::rtl::OUString aName = GenerateName(pNewFormData);
+ pNewFormData->SetText(aName);
+
+ Reference< XPropertySet > xPropertySet(xNewForm, UNO_QUERY);
+ if (!xPropertySet.is())
+ return;
+ try
+ {
+ xPropertySet->setPropertyValue( FM_PROP_NAME, makeAny(aName) );
+ // a form should always have the command type table as default
+ xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE)));
+ }
+ catch ( const Exception& )
+ {
+ DBG_ERROR("NavigatorTree::NewForm : could not set esssential properties !");
+ }
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Form einfuegen
+ GetNavModel()->Insert( pNewFormData, LIST_APPEND, sal_True );
+
+ //////////////////////////////////////////////////////////////////////
+ // Neue Form als aktive Form setzen
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if( pFormShell )
+ {
+ InterfaceBag aSelection;
+ aSelection.insert( Reference< XInterface >( xNewForm, UNO_QUERY ) );
+ pFormShell->GetImpl()->setCurrentSelection( aSelection );
+
+ pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES,sal_True,sal_True);
+ }
+ GetNavModel()->SetModified();
+
+ //////////////////////////////////////////////////////////////////////
+ // In EditMode schalten
+ SvLBoxEntry* pNewEntry = FindEntry( pNewFormData );
+ EditEntry( pNewEntry );
+ }
+
+ //------------------------------------------------------------------------
+ FmControlData* NavigatorTree::NewControl( const ::rtl::OUString& rServiceName, SvLBoxEntry* pParentEntry, sal_Bool bEditName )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NewControl" );
+ //////////////////////////////////////////////////////////////////////
+ // ParentForm holen
+ if (!GetNavModel()->GetFormShell())
+ return NULL;
+ if (!IsFormEntry(pParentEntry))
+ return NULL;
+
+ FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData();;
+ Reference< XForm > xParentForm( pParentFormData->GetFormIface());
+
+ //////////////////////////////////////////////////////////////////////
+ // Neue Component erzeugen
+ Reference< XFormComponent > xNewComponent(::comphelper::getProcessServiceFactory()->createInstance(rServiceName), UNO_QUERY);
+ if (!xNewComponent.is())
+ return NULL;
+
+ FmControlData* pNewFormControlData = new FmControlData( xNewComponent, m_aNavigatorImages, pParentFormData );
+
+ //////////////////////////////////////////////////////////////////////
+ // Namen setzen
+ FmFormView* pFormView = GetNavModel()->GetFormShell()->GetFormView();
+ SdrPageView* pPageView = pFormView->GetSdrPageView();
+ FmFormPage* pPage = (FmFormPage*)pPageView->GetPage();
+
+ ::rtl::OUString sName = pPage->GetImpl().setUniqueName( xNewComponent, xParentForm );
+
+ pNewFormControlData->SetText( sName );
+
+ //////////////////////////////////////////////////////////////////////
+ // FormComponent einfuegen
+ GetNavModel()->Insert( pNewFormControlData, LIST_APPEND, sal_True );
+ GetNavModel()->SetModified();
+
+ if (bEditName)
+ {
+ //////////////////////////////////////////////////////////////////////
+ // In EditMode schalten
+ SvLBoxEntry* pNewEntry = FindEntry( pNewFormControlData );
+ Select( pNewEntry, sal_True );
+ EditEntry( pNewEntry );
+ }
+
+ return pNewFormControlData;
+ }
+
+ //------------------------------------------------------------------------
+ ::rtl::OUString NavigatorTree::GenerateName( FmEntryData* pEntryData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::GenerateName" );
+ const sal_uInt16 nMaxCount = 99;
+ ::rtl::OUString aNewName;
+
+ //////////////////////////////////////////////////////////////////////
+ // BasisNamen erzeugen
+ UniString aBaseName;
+ if( pEntryData->ISA(FmFormData) )
+ aBaseName = SVX_RES( RID_STR_STDFORMNAME );
+
+ else if( pEntryData->ISA(FmControlData) )
+ aBaseName = SVX_RES( RID_STR_CONTROL );
+
+ //////////////////////////////////////////////////////////////////////
+ // Neuen Namen erstellen
+ FmFormData* pFormParentData = (FmFormData*)pEntryData->GetParent();
+
+ for( sal_Int32 i=0; i<nMaxCount; i++ )
+ {
+ aNewName = aBaseName;
+ if( i>0 )
+ {
+ aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
+ aNewName += ::rtl::OUString::valueOf(i).getStr();
+ }
+
+ if( GetNavModel()->FindData(aNewName, pFormParentData,sal_False) == NULL )
+ break;
+ }
+
+ return aNewName;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::EditedEntry" );
+ if (EditingCanceled())
+ return sal_True;
+
+ GrabFocus();
+ FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData();
+ sal_Bool bRes = GetNavModel()->Rename( pEntryData, rNewText);
+ if( !bRes )
+ {
+ m_pEditEntry = pEntry;
+ nEditEvent = Application::PostUserEvent( LINK(this, NavigatorTree, OnEdit) );
+ } else
+ SetCursor(pEntry, sal_True);
+
+ return bRes;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NavigatorTree, OnEdit, void*, EMPTYARG )
+ {
+ nEditEvent = 0;
+ EditEntry( m_pEditEntry );
+ m_pEditEntry = NULL;
+
+ return 0L;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NavigatorTree, OnDropActionTimer, void*, EMPTYARG )
+ {
+ if (--m_aTimerCounter > 0)
+ return 0L;
+
+ switch ( m_aDropActionType )
+ {
+ case DA_EXPANDNODE:
+ {
+ SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered);
+ if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
+ // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich
+ // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ...
+ // aber ich denke, die BK sollte es auch so vertragen
+ Expand(pToExpand);
+
+ // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun
+ m_aDropActionTimer.Stop();
+ }
+ break;
+
+ case DA_SCROLLUP :
+ ScrollOutputArea( 1 );
+ m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
+ break;
+
+ case DA_SCROLLDOWN :
+ ScrollOutputArea( -1 );
+ m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
+ break;
+
+ }
+
+ return 0L;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/)
+ {
+ m_sdiState = SDI_DIRTY;
+
+ if (IsSelectionHandlingLocked())
+ return 0L;
+
+ if (m_aSynchronizeTimer.IsActive())
+ m_aSynchronizeTimer.Stop();
+
+ m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY);
+ m_aSynchronizeTimer.Start();
+
+ return 0L;
+ }
+
+ //------------------------------------------------------------------------
+ IMPL_LINK(NavigatorTree, OnSynchronizeTimer, void*, EMPTYARG)
+ {
+ SynchronizeMarkList();
+ return 0L;
+ }
+
+
+ //------------------------------------------------------------------------
+ IMPL_LINK( NavigatorTree, OnClipboardAction, void*, EMPTYARG )
+ {
+ if ( !m_aControlExchange.isClipboardOwner() )
+ {
+ if ( doingKeyboardCut() )
+ {
+ for ( ListBoxEntrySet::const_iterator i = m_aCutEntries.begin();
+ i != m_aCutEntries.end();
+ ++i
+ )
+ {
+ SvLBoxEntry* pEntry = *i;
+ if ( !pEntry )
+ continue;
+
+ pEntry->SetFlags( pEntry->GetFlags() & ~SV_ENTRYFLAG_SEMITRANSPARENT );
+ InvalidateEntry( pEntry );
+ }
+ ListBoxEntrySet aEmpty;
+ m_aCutEntries.swap( aEmpty );
+
+ m_bKeyboardCut = sal_False;
+ }
+ }
+ return 0L;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::ShowSelectionProperties(sal_Bool bForce)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ShowSelectionProperties" );
+ // zuerst brauche ich die FormShell
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if (!pFormShell)
+ // keine Shell -> ich koennte kein curObject setzen -> raus
+ return;
+
+ CollectSelectionData(SDI_ALL);
+ DBG_ASSERT( m_nFormsSelected + m_nControlsSelected + (m_bRootSelected ? 1 : 0) == m_arrCurrentSelection.Count(),
+ "NavigatorTree::ShowSelectionProperties : selection meta data invalid !");
+
+
+ InterfaceBag aSelection;
+ sal_Bool bSetSelectionAsMarkList = sal_False;
+
+ if (m_bRootSelected)
+ ; // no properties for the root, neither for single nor for multi selection
+ else if ( m_nFormsSelected + m_nControlsSelected == 0 ) // none of the two should be less 0
+ ; // no selection -> no properties
+ else if ( m_nFormsSelected * m_nControlsSelected != 0 )
+ ; // mixed selection -> no properties
+ else
+ { // either only forms, or only controls are selected
+ if (m_arrCurrentSelection.Count() == 1)
+ {
+ if (m_nFormsSelected > 0)
+ { // es ist genau eine Form selektiert
+ FmFormData* pFormData = (FmFormData*)m_arrCurrentSelection.GetObject(0)->GetUserData();
+ aSelection.insert( Reference< XInterface >( pFormData->GetFormIface(), UNO_QUERY ) );
+ }
+ else
+ { // es ist genau ein Control selektiert (egal ob hidden oder normal)
+ FmEntryData* pEntryData = (FmEntryData*)m_arrCurrentSelection.GetObject(0)->GetUserData();
+
+ aSelection.insert( Reference< XInterface >( pEntryData->GetElement(), UNO_QUERY ) );
+ }
+ }
+ else
+ { // wir haben eine MultiSelection, also muessen wir ein MultiSet dafuer aufbauen
+ if (m_nFormsSelected > 0)
+ { // ... nur Forms
+ // erstmal die PropertySet-Interfaces der Forms einsammeln
+ for ( sal_Int32 i = 0; i < m_nFormsSelected; ++i )
+ {
+ FmFormData* pFormData = (FmFormData*)m_arrCurrentSelection.GetObject((USHORT)i)->GetUserData();
+ aSelection.insert( pFormData->GetPropertySet().get() );
+ }
+ }
+ else
+ { // ... nur Controls
+ if (m_nHiddenControls == m_nControlsSelected)
+ { // ein MultiSet fuer die Properties der hidden controls
+ for ( sal_Int32 i = 0; i < m_nHiddenControls; ++i )
+ {
+ FmEntryData* pEntryData = (FmEntryData*)m_arrCurrentSelection.GetObject((USHORT)i)->GetUserData();
+ aSelection.insert( pEntryData->GetPropertySet().get() );
+ }
+ }
+ else if (m_nHiddenControls == 0)
+ { // nur normale Controls
+ bSetSelectionAsMarkList = sal_True;
+ }
+ }
+ }
+
+ }
+
+ // und dann meine Form und mein SelObject
+ if ( bSetSelectionAsMarkList )
+ pFormShell->GetImpl()->setCurrentSelectionFromMark( pFormShell->GetFormView()->GetMarkedObjectList() );
+ else
+ pFormShell->GetImpl()->setCurrentSelection( aSelection );
+
+ if ( pFormShell->GetImpl()->IsPropBrwOpen() || bForce )
+ {
+ // und jetzt kann ich das Ganze dem PropertyBrowser uebergeben
+ pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::DeleteSelection()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::DeleteSelection" );
+ // die Root darf ich natuerlich nicht mitloeschen
+ sal_Bool bRootSelected = IsSelected(m_pRootEntry);
+ ULONG nSelectedEntries = GetSelectionCount();
+ if (bRootSelected && (nSelectedEntries > 1)) // die Root plus andere Elemente ?
+ Select(m_pRootEntry, sal_False); // ja -> die Root raus
+
+ if ((nSelectedEntries == 0) || bRootSelected) // immer noch die Root ?
+ return; // -> sie ist das einzige selektierte -> raus
+
+ DBG_ASSERT(!m_bPrevSelectionMixed, "NavigatorTree::DeleteSelection() : loeschen nicht erlaubt wenn Markierung und Selektion nciht konsistent");
+
+ // ich brauche unten das FormModel ...
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if (!pFormShell)
+ return;
+ FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
+ if (!pFormModel)
+ return;
+
+ // jetzt muss ich noch die DeleteList etwas absichern : wenn man ein Formular und ein abhaengiges
+ // Element loescht - und zwar in dieser Reihenfolge - dann ist der SvLBoxEntryPtr des abhaengigen Elementes
+ // natuerlich schon ungueltig, wenn es geloescht werden soll ... diesen GPF, den es dann mit Sicherheit gibt,
+ // gilt es zu verhindern, also die 'normalisierte' Liste
+ CollectSelectionData( SDI_NORMALIZED );
+
+ // see below for why we need this mapping from models to shapes
+ FmFormView* pFormView = pFormShell->GetFormView();
+ SdrPageView* pPageView = pFormView ? pFormView->GetSdrPageView() : NULL;
+ SdrPage* pPage = pPageView ? pPageView->GetPage() : NULL;
+ DBG_ASSERT( pPage, "NavigatorTree::DeleteSelection: invalid form page!" );
+
+ MapModelToShape aModelShapes;
+ if ( pPage )
+ collectShapeModelMapping( pPage, aModelShapes );
+
+ // problem: we have to use ExplorerModel::Remove, since only this one properly deletes Form objects.
+ // But, the controls themself must be deleted via DeleteMarked (else, the Writer has some problems
+ // somewhere). In case I'd first delete the structure, then the controls, the UNDO would not work
+ // (since UNDO then would mean to first restore the controls, then the structure, means their parent
+ // form). The other way round, the EntryDatas would be invalid, if I'd first delete the controls and
+ // then go on to the strucure. This means I have to delete the forms *after* the normal controls, so
+ // that during UNDO, they're restored in the proper order.
+ pFormShell->GetImpl()->EnableTrackProperties(sal_False);
+ USHORT i;
+ for (i = m_arrCurrentSelection.Count(); i>0; --i)
+ {
+ FmEntryData* pCurrent = (FmEntryData*)(m_arrCurrentSelection.GetObject(i - 1)->GetUserData());
+
+ // eine Form ?
+ sal_Bool bIsForm = pCurrent->ISA(FmFormData);
+
+ // da ich das Loeschen im folgenden der View ueberlasse und dabei auf deren MarkList aufbaue, im Normalfall aber bei
+ // einem makierten Formular nur die direkt, nicht die indirekt abhaengigen Controls markiert werden, muss ich das hier
+ // noch nachholen
+ if (bIsForm)
+ MarkViewObj((FmFormData*)pCurrent, sal_True, sal_True); // das zweite sal_True heisst "deep"
+
+ // ein hidden control ?
+ sal_Bool bIsHidden = IsHiddenControl(pCurrent);
+
+ // Forms und hidden Controls muss ich behalten, alles andere nicht
+ if (!bIsForm && !bIsHidden)
+ {
+ // well, no form and no hidden control -> we can remove it from m_arrCurrentSelection, as it will
+ // be deleted automatically. This is because for every model (except forms and hidden control models)
+ // there exist a shape, which is marked _if_and_only_if_ the model is selected in our tree.
+ if ( aModelShapes.find( pCurrent->GetElement() ) != aModelShapes.end() )
+ {
+ // if there's a shape for the current entry, then either it is marked or it is in a
+ // hidden layer (#i28502#), or something like this.
+ // In the first case, it will be deleted below, in the second case, we currently don't
+ // delete it, as there's no real (working!) API for this, neither in UNO nor in non-UNO.
+ m_arrCurrentSelection.Remove( i - 1, 1 );
+ }
+ // In case there is no shape for the current entry, we keep the entry in m_arrCurrentSelection,
+ // since then we can definately remove it.
+ // #103597#
+ }
+ }
+ pFormShell->GetImpl()->EnableTrackProperties(sal_True);
+
+ // let the view delete the marked controls
+ pFormShell->GetFormView()->DeleteMarked();
+
+ // start UNDO at this point. Unfortunately, this results in 2 UNDO actions, since DeleteMarked is
+ // creating an own one. However, if we'd move it before DeleteMarked, Writer does not really like
+ // this ... :(
+ // 2004-07-05 - #i31038# - fs@openoffice.org
+ {
+ // ---------------
+ // initialize UNDO
+ String aUndoStr;
+ if ( m_arrCurrentSelection.Count() == 1 )
+ {
+ aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE);
+ if (m_nFormsSelected)
+ aUndoStr.SearchAndReplaceAscii( "#", SVX_RES( RID_STR_FORM ) );
+ else
+ // it must be a control (else the root would be selected, but it cannot be deleted)
+ aUndoStr.SearchAndReplaceAscii( "#", SVX_RES( RID_STR_CONTROL ) );
+ }
+ else
+ {
+ aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE);
+ aUndoStr.SearchAndReplaceAscii( "#", String::CreateFromInt32( m_arrCurrentSelection.Count() ) );
+ }
+ pFormModel->BegUndo(aUndoStr);
+ }
+
+ // remove remaining structure
+ for (i=0; i<m_arrCurrentSelection.Count(); ++i)
+ {
+ FmEntryData* pCurrent = (FmEntryData*)(m_arrCurrentSelection.GetObject(i)->GetUserData());
+
+ // if the entry still has children, we skipped deletion of one of those children.
+ // This may for instance be because the shape is in a hidden layer, where we're unable
+ // to remove it
+ if ( pCurrent->GetChildList()->size() )
+ continue;
+
+ // noch ein kleines Problem, bevor ich das ganz loesche : wenn es eine Form ist und die Shell diese als CurrentObject
+ // kennt, dann muss ich ihr das natuerlich ausreden
+ if (pCurrent->ISA(FmFormData))
+ {
+ Reference< XForm > xCurrentForm( static_cast< FmFormData* >( pCurrent )->GetFormIface() );
+ if ( pFormShell->GetImpl()->getCurrentForm() == xCurrentForm ) // die Shell kennt die zu loeschende Form ?
+ pFormShell->GetImpl()->forgetCurrentForm(); // -> wegnehmen ...
+ }
+ GetNavModel()->Remove(pCurrent, sal_True);
+ }
+ pFormModel->EndUndo();
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::CollectSelectionData(SELDATA_ITEMS sdiHow)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::CollectSelectionData" );
+ DBG_ASSERT(sdiHow != SDI_DIRTY, "NavigatorTree::CollectSelectionData : ever thought about your parameter ? DIRTY ?");
+ if (sdiHow == m_sdiState)
+ return;
+
+ m_arrCurrentSelection.Remove((sal_uInt16)0, m_arrCurrentSelection.Count());
+ m_nFormsSelected = m_nControlsSelected = m_nHiddenControls = 0;
+ m_bRootSelected = sal_False;
+
+ SvLBoxEntry* pSelectionLoop = FirstSelected();
+ while (pSelectionLoop)
+ {
+ // erst mal die Zaehlung der verschiedenen Elemente
+ if (pSelectionLoop == m_pRootEntry)
+ m_bRootSelected = sal_True;
+ else
+ {
+ if (IsFormEntry(pSelectionLoop))
+ ++m_nFormsSelected;
+ else
+ {
+ ++m_nControlsSelected;
+ if (IsHiddenControl((FmEntryData*)(pSelectionLoop->GetUserData())))
+ ++m_nHiddenControls;
+ }
+ }
+
+ if (sdiHow == SDI_NORMALIZED)
+ {
+ // alles, was schon einen selektierten Vorfahr hat, nicht mitnehmen
+ if (pSelectionLoop == m_pRootEntry)
+ m_arrCurrentSelection.Insert(pSelectionLoop);
+ else
+ {
+ SvLBoxEntry* pParentLoop = GetParent(pSelectionLoop);
+ while (pParentLoop)
+ {
+ // eigentlich muesste ich testen, ob das Parent in der m_arrCurrentSelection steht ...
+ // Aber wenn es selektiert ist, dann steht es in m_arrCurrentSelection, oder wenigstens einer seiner Vorfahren,
+ // wenn der auch schon selektiert war. In beiden Faellen reicht also die Abfrage IsSelected
+ if (IsSelected(pParentLoop))
+ break;
+ else
+ {
+ if (m_pRootEntry == pParentLoop)
+ {
+ // bis (exclusive) zur Root gab es kein selektiertes Parent -> der Eintrag gehoert in die normalisierte Liste
+ m_arrCurrentSelection.Insert(pSelectionLoop);
+ break;
+ }
+ else
+ pParentLoop = GetParent(pParentLoop);
+ }
+ }
+ }
+ }
+ else if (sdiHow == SDI_NORMALIZED_FORMARK)
+ {
+ SvLBoxEntry* pParent = GetParent(pSelectionLoop);
+ if (!pParent || !IsSelected(pParent) || IsFormEntry(pSelectionLoop))
+ m_arrCurrentSelection.Insert(pSelectionLoop);
+ }
+ else
+ m_arrCurrentSelection.Insert(pSelectionLoop);
+
+
+ pSelectionLoop = NextSelected(pSelectionLoop);
+ }
+
+ m_sdiState = sdiHow;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::SynchronizeSelection(FmEntryDataArray& arredToSelect)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeSelection" );
+ LockSelectionHandling();
+ if (arredToSelect.Count() == 0)
+ {
+ SelectAll(sal_False);
+ }
+ else
+ {
+ // erst mal gleiche ich meine aktuelle Selektion mit der geforderten SelectList ab
+ SvLBoxEntry* pSelection = FirstSelected();
+ while (pSelection)
+ {
+ FmEntryData* pCurrent = (FmEntryData*)pSelection->GetUserData();
+ if (pCurrent != NULL)
+ {
+ sal_uInt16 nPosition;
+ if ( arredToSelect.Seek_Entry(pCurrent, &nPosition) )
+ { // der Entry ist schon selektiert, steht aber auch in der SelectList -> er kann aus letzterer
+ // raus
+ arredToSelect.Remove(nPosition, 1);
+ } else
+ { // der Entry ist selektiert, aber steht nicht in der SelectList -> Selektion rausnehmen
+ Select(pSelection, sal_False);
+ // und sichtbar machen (kann ja sein, dass das die einzige Modifikation ist, die ich hier in dem
+ // ganzen Handler mache, dann sollte das zu sehen sein)
+ MakeVisible(pSelection);
+ }
+ }
+ else
+ Select(pSelection, sal_False);
+
+ pSelection = NextSelected(pSelection);
+ }
+
+ // jetzt habe ich in der SelectList genau die Eintraege, die noch selektiert werden muessen
+ // zwei Moeglichkeiten : 1) ich gehe durch die SelectList, besorge mir zu jedem Eintrag meinen SvLBoxEntry
+ // und selektiere diesen (waere irgendwie intuitiver ;)) 2) ich gehe durch alle meine SvLBoxEntries und selektiere
+ // genau die, die ich in der SelectList finde
+ // 1) braucht O(k*n) (k=Laenge der SelectList, n=Anzahl meiner Entries), plus den Fakt, dass FindEntry nicht den
+ // Pointer auf die UserDaten vergleicht, sondern ein aufwendigeres IsEqualWithoutChilds durchfuehrt
+ // 2) braucht O(n*log k), dupliziert aber etwas Code (naemlich den aus FindEntry)
+ // da das hier eine relativ oft aufgerufenen Stelle sein koennte (bei jeder Aenderung in der Markierung in der View !),
+ // nehme ich doch lieber letzteres
+ SvLBoxEntry* pLoop = First();
+ while( pLoop )
+ {
+ FmEntryData* pCurEntryData = (FmEntryData*)pLoop->GetUserData();
+ sal_uInt16 nPosition;
+ if ( arredToSelect.Seek_Entry(pCurEntryData, &nPosition) )
+ {
+ Select(pLoop, sal_True);
+ MakeVisible(pLoop);
+ SetCursor(pLoop, sal_True);
+ }
+
+ pLoop = Next( pLoop );
+ }
+ }
+ UnlockSelectionHandling();
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::SynchronizeSelection()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeSelection" );
+ // Shell und View
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if(!pFormShell) return;
+
+ FmFormView* pFormView = pFormShell->GetFormView();
+ if (!pFormView) return;
+
+ GetNavModel()->BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::SynchronizeMarkList()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeMarkList" );
+ // die Shell werde ich brauchen ...
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if (!pFormShell) return;
+
+ CollectSelectionData(SDI_NORMALIZED_FORMARK);
+
+ // Die View soll jetzt kein Notify bei einer Aenderung der MarkList rauslassen
+ pFormShell->GetImpl()->EnableTrackProperties(sal_False);
+
+ UnmarkAllViewObj();
+
+ for (sal_uInt32 i=0; i<m_arrCurrentSelection.Count(); ++i)
+ {
+ SvLBoxEntry* pSelectionLoop = m_arrCurrentSelection.GetObject((USHORT)i);
+ // Bei Formselektion alle Controls dieser Form markieren
+ if (IsFormEntry(pSelectionLoop) && (pSelectionLoop != m_pRootEntry))
+ MarkViewObj((FmFormData*)pSelectionLoop->GetUserData(), sal_True, sal_False);
+
+ // Bei Controlselektion Control-SdrObjects markieren
+ else if (IsFormComponentEntry(pSelectionLoop))
+ {
+ FmControlData* pControlData = (FmControlData*)pSelectionLoop->GetUserData();
+ if (pControlData)
+ {
+ /////////////////////////////////////////////////////////////////
+ // Beim HiddenControl kann kein Object selektiert werden
+ Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
+ if (!xFormComponent.is())
+ continue;
+ Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
+ if (!xSet.is())
+ continue;
+
+ sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID));
+ if (nClassId != FormComponentType::HIDDENCONTROL)
+ MarkViewObj(pControlData, sal_True, sal_True);
+ }
+ }
+ }
+
+ // wenn der PropertyBrowser offen ist, muss ich den entsprechend meiner Selektion anpassen
+ // (NICHT entsprechend der MarkList der View : wenn ich ein Formular selektiert habe, sind in der
+ // View alle zugehoerigen Controls markiert, trotzdem moechte ich natuerlich die Formular-Eigenschaften
+ // sehen)
+ ShowSelectionProperties(sal_False);
+
+ // Flag an View wieder zuruecksetzen
+ pFormShell->GetImpl()->EnableTrackProperties(sal_True);
+
+ // wenn jetzt genau eine Form selektiert ist, sollte die Shell das als CurrentForm mitbekommen
+ // (wenn SelectionHandling nicht locked ist, kuemmert sich die View eigentlich in MarkListHasChanged drum,
+ // aber der Mechanismus greift zum Beispiel nicht, wenn die Form leer ist)
+ if ((m_arrCurrentSelection.Count() == 1) && (m_nFormsSelected == 1))
+ {
+ FmFormData* pSingleSelectionData = PTR_CAST( FmFormData, static_cast< FmEntryData* >( FirstSelected()->GetUserData() ) );
+ DBG_ASSERT( pSingleSelectionData, "NavigatorTree::SynchronizeMarkList: invalid selected form!" );
+ if ( pSingleSelectionData )
+ {
+ InterfaceBag aSelection;
+ aSelection.insert( Reference< XInterface >( pSingleSelectionData->GetFormIface(), UNO_QUERY ) );
+ pFormShell->GetImpl()->setCurrentSelection( aSelection );
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::IsHiddenControl(FmEntryData* pEntryData)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsHiddenControl" );
+ if (pEntryData == NULL) return sal_False;
+
+ Reference< XPropertySet > xProperties( pEntryData->GetPropertySet() );
+ if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
+ {
+ Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID );
+ return (::comphelper::getINT16(aClassID) == FormComponentType::HIDDENCONTROL);
+ }
+ return sal_False;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTree::Select( SvLBoxEntry* pEntry, sal_Bool bSelect )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Select" );
+ if (bSelect == IsSelected(pEntry)) // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;)
+ return sal_True;
+
+ return SvTreeListBox::Select(pEntry, bSelect );
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTree::UnmarkAllViewObj()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::UnmarkAllViewObj" );
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if( !pFormShell )
+ return;
+ FmFormView* pFormView = pFormShell->GetFormView();
+ pFormView->UnMarkAll();
+ }
+ //------------------------------------------------------------------------
+ void NavigatorTree::MarkViewObj(FmFormData* pFormData, sal_Bool bMark, sal_Bool bDeep )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObjects" );
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if( !pFormShell )
+ return;
+
+ // first collect all sdrobjects
+ ::std::set< Reference< XFormComponent > > aObjects;
+ CollectObjects(pFormData,bDeep,aObjects);
+
+ //////////////////////////////////////////////////////////////////////
+ // In der Page das entsprechende SdrObj finden und selektieren
+ FmFormView* pFormView = pFormShell->GetFormView();
+ SdrPageView* pPageView = pFormView->GetSdrPageView();
+ SdrPage* pPage = pPageView->GetPage();
+ //FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage );
+
+ SdrObjListIter aIter( *pPage );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pSdrObject = aIter.Next();
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
+ if ( !pFormObject )
+ continue;
+
+ Reference< XFormComponent > xControlModel( pFormObject->GetUnoControlModel(),UNO_QUERY );
+ if ( xControlModel.is() && aObjects.find(xControlModel) != aObjects.end() && bMark != pFormView->IsObjMarked( pSdrObject ) )
+ {
+ // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
+ pFormView->MarkObj( pSdrObject, pPageView, !bMark, sal_False );
+ }
+ } // while ( aIter.IsMore() )
+ if ( bMark )
+ {
+ // make the mark visible
+ ::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
+ for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
+ {
+ SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
+ OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
+ if ( ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) && !aMarkRect.IsEmpty() )
+ {
+ pFormView->MakeVisible( aMarkRect, (Window&)rOutDev );
+ }
+ } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
+ }
+ }
+ //------------------------------------------------------------------------
+ void NavigatorTree::CollectObjects(FmFormData* pFormData, sal_Bool bDeep, ::std::set< Reference< XFormComponent > >& _rObjects)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObjects" );
+ FmEntryDataList* pChildList = pFormData->GetChildList();
+ FmEntryData* pEntryData;
+ FmControlData* pControlData;
+ for( size_t i = 0; i < pChildList->size(); ++i )
+ {
+ pEntryData = pChildList->at( i );
+ if( pEntryData->ISA(FmControlData) )
+ {
+ pControlData = (FmControlData*)pEntryData;
+ _rObjects.insert(pControlData->GetFormComponent());
+ } // if( pEntryData->ISA(FmControlData) )
+ else if (bDeep && (pEntryData->ISA(FmFormData)))
+ CollectObjects((FmFormData*)pEntryData,bDeep,_rObjects);
+ } // for( sal_uInt32 i=0; i<pChildList->Count(); i++ )
+ }
+ //------------------------------------------------------------------------
+ void NavigatorTree::MarkViewObj( FmControlData* pControlData, sal_Bool bMarkHandles, sal_Bool bMark)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObj" );
+ if( !pControlData )
+ return;
+ FmFormShell* pFormShell = GetNavModel()->GetFormShell();
+ if( !pFormShell )
+ return;
+
+ //////////////////////////////////////////////////////////////////////
+ // In der Page das entsprechende SdrObj finden und selektieren
+ FmFormView* pFormView = pFormShell->GetFormView();
+ Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
+ SdrPageView* pPageView = pFormView->GetSdrPageView();
+ SdrPage* pPage = pPageView->GetPage();
+
+ bool bPaint = false;
+ SdrObjListIter aIter( *pPage );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pSdrObject = aIter.Next();
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
+ if ( !pFormObject )
+ continue;
+
+ Reference< XInterface > xControlModel( pFormObject->GetUnoControlModel() );
+ if ( xControlModel != xFormComponent )
+ continue;
+
+ // mark the object
+ if ( bMark != pFormView->IsObjMarked( pSdrObject ) )
+ // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
+ pFormView->MarkObj( pSdrObject, pPageView, !bMark, sal_False );
+
+ if ( !bMarkHandles || !bMark )
+ continue;
+
+ bPaint = true;
+
+ } // while ( aIter.IsMore() )
+ if ( bPaint )
+ {
+ // make the mark visible
+ ::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
+ for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
+ {
+ SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
+ OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
+ if ( OUTDEV_WINDOW == rOutDev.GetOutDevType() )
+ {
+ pFormView->MakeVisible( aMarkRect, (Window&)rOutDev );
+ }
+ } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
+ }
+ }
+
+//............................................................................
+} // namespace svxform
+//............................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/navigatortreemodel.cxx b/svx/source/form/navigatortreemodel.cxx
new file mode 100644
index 000000000000..b792200956d8
--- /dev/null
+++ b/svx/source/form/navigatortreemodel.cxx
@@ -0,0 +1,1120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/dialmgr.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/fmpage.hxx>
+#include <svx/fmglob.hxx>
+#include "svditer.hxx"
+#include <svx/svdogrp.hxx>
+#include <svx/svdpagv.hxx>
+
+#include "fmprop.hrc"
+
+#include "fmundo.hxx"
+#include "fmhelp.hrc"
+#include "fmexpl.hrc"
+#include "fmexpl.hxx"
+#include "fmresids.hrc"
+#include "fmshimp.hxx"
+#include "fmobj.hxx"
+#include <sfx2/objsh.hxx>
+#include <tools/diagnose_ex.h>
+#include <rtl/logfile.hxx>
+#include <com/sun/star/container/XContainer.hpp>
+
+//............................................................................
+namespace svxform
+{
+//............................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::form;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::script;
+ using namespace ::com::sun::star::sdb;
+
+ //========================================================================
+ // class OFormComponentObserver
+ //========================================================================
+ //------------------------------------------------------------------------
+ OFormComponentObserver::OFormComponentObserver(NavigatorTreeModel* _pModel)
+ :m_pNavModel(_pModel)
+ ,m_nLocks(0)
+ ,m_bCanUndo(sal_True)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::OFormComponentObserver" );
+ }
+
+ // XPropertyChangeListener
+ //------------------------------------------------------------------------
+ void SAL_CALL OFormComponentObserver::disposing(const EventObject& Source) throw( RuntimeException )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::disposing" );
+ Remove( Source.Source );
+ }
+
+ //------------------------------------------------------------------------
+ void SAL_CALL OFormComponentObserver::propertyChange(const PropertyChangeEvent& evt) throw(RuntimeException)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::propertyChange" );
+ if( !m_pNavModel ) return;
+ if( evt.PropertyName != FM_PROP_NAME ) return;
+
+ Reference< XFormComponent > xFormComponent(evt.Source, UNO_QUERY);
+ Reference< XForm > xForm(evt.Source, UNO_QUERY);
+
+ FmEntryData* pEntryData( NULL );
+ if( xForm.is() )
+ pEntryData = m_pNavModel->FindData( xForm, m_pNavModel->GetRootList() );
+ else if( xFormComponent.is() )
+ pEntryData = m_pNavModel->FindData( xFormComponent, m_pNavModel->GetRootList() );
+
+ if( pEntryData )
+ {
+ ::rtl::OUString aNewName = ::comphelper::getString(evt.NewValue);
+ pEntryData->SetText( aNewName );
+ FmNavNameChangedHint aNameChangedHint( pEntryData, aNewName );
+ m_pNavModel->Broadcast( aNameChangedHint );
+ }
+ }
+
+ // XContainerListener
+ //------------------------------------------------------------------------------
+ void SAL_CALL OFormComponentObserver::elementInserted(const ContainerEvent& evt) throw(RuntimeException)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementInserted" );
+ if (IsLocked() || !m_pNavModel)
+ return;
+
+ // keine Undoaction einfuegen
+ m_bCanUndo = sal_False;
+
+ Reference< XInterface > xTemp;
+ evt.Element >>= xTemp;
+ Insert(xTemp, ::comphelper::getINT32(evt.Accessor));
+
+ m_bCanUndo = sal_True;
+ }
+
+ //------------------------------------------------------------------------------
+ void OFormComponentObserver::Insert(const Reference< XInterface > & xIface, sal_Int32 nIndex)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::Insert" );
+ Reference< XForm > xForm(xIface, UNO_QUERY);
+ if (xForm.is())
+ {
+ m_pNavModel->InsertForm(xForm, sal_uInt32(nIndex));
+ Reference< XIndexContainer > xContainer(xForm, UNO_QUERY);
+ Reference< XInterface > xTemp;
+ for (sal_Int32 i = 0; i < xContainer->getCount(); i++)
+ {
+ xContainer->getByIndex(i) >>= xTemp;
+ Insert(xTemp, i);
+ }
+ }
+ else
+ {
+ Reference< XFormComponent > xFormComp(xIface, UNO_QUERY);
+ if (xFormComp.is())
+ m_pNavModel->InsertFormComponent(xFormComp, sal_uInt32(nIndex));
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OFormComponentObserver::elementReplaced(const ContainerEvent& evt) throw(RuntimeException)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementReplaced" );
+ if (IsLocked() || !m_pNavModel)
+ return;
+
+ m_bCanUndo = sal_False;
+
+ // EntryData loeschen
+ Reference< XFormComponent > xReplaced;
+ evt.ReplacedElement >>= xReplaced;
+ FmEntryData* pEntryData = m_pNavModel->FindData(xReplaced, m_pNavModel->GetRootList(), sal_True);
+ if (pEntryData)
+ {
+ if (pEntryData->ISA(FmControlData))
+ {
+ Reference< XFormComponent > xComp;
+ evt.Element >>= xComp;
+ DBG_ASSERT(xComp.is(), "OFormComponentObserver::elementReplaced : invalid argument !");
+ // an einer FmControlData sollte eine XFormComponent haengen
+ m_pNavModel->ReplaceFormComponent(xReplaced, xComp);
+ }
+ else if (pEntryData->ISA(FmFormData))
+ {
+ DBG_ERROR("replacing forms not implemented yet !");
+ }
+ }
+
+ m_bCanUndo = sal_True;
+ }
+
+ //------------------------------------------------------------------------------
+ void OFormComponentObserver::Remove( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::Remove" );
+ if (IsLocked() || !m_pNavModel)
+ return;
+
+ m_bCanUndo = sal_False;
+
+ //////////////////////////////////////////////////////////
+ // EntryData loeschen
+ FmEntryData* pEntryData = m_pNavModel->FindData( _rxElement, m_pNavModel->GetRootList(), sal_True );
+ if (pEntryData)
+ m_pNavModel->Remove(pEntryData);
+
+ m_bCanUndo = sal_True;
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OFormComponentObserver::elementRemoved(const ContainerEvent& evt) throw(RuntimeException)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "OFormComponentObserver::elementRemoved" );
+ Reference< XInterface > xElement;
+ evt.Element >>= xElement;
+ Remove( xElement );
+ }
+
+ //========================================================================
+ // class NavigatorTreeModel
+ //========================================================================
+
+ //------------------------------------------------------------------------
+ NavigatorTreeModel::NavigatorTreeModel( const ImageList& _rNormalImages )
+ :m_pFormShell(NULL)
+ ,m_pFormPage(NULL)
+ ,m_pFormModel(NULL)
+ ,m_aNormalImages( _rNormalImages )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::NavigatorTreeModel" );
+ m_pPropChangeList = new OFormComponentObserver(this);
+ m_pPropChangeList->acquire();
+ m_pRootList = new FmEntryDataList();
+ }
+
+ //------------------------------------------------------------------------
+ NavigatorTreeModel::~NavigatorTreeModel()
+ {
+ //////////////////////////////////////////////////////////////////////
+ // Als Listener abmelden
+ if( m_pFormShell)
+ {
+ FmFormModel* pFormModel = m_pFormShell->GetFormModel();
+ if( pFormModel && IsListening(*pFormModel))
+ EndListening( *pFormModel );
+
+ if (IsListening(*m_pFormShell))
+ EndListening(*m_pFormShell);
+ }
+
+ Clear();
+ delete m_pRootList;
+ m_pPropChangeList->ReleaseModel();
+ m_pPropChangeList->release();
+ }
+
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::SetModified( sal_Bool bMod )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::SetModified" );
+ if( !m_pFormShell ) return;
+ SfxObjectShell* pObjShell = m_pFormShell->GetFormModel()->GetObjectShell();
+ if( !pObjShell ) return;
+ pObjShell->SetModified( bMod );
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::Clear()
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Clear" );
+ Reference< XNameContainer > xForms( GetForms());
+ Reference< XContainer > xContainer(xForms, UNO_QUERY);
+ if (xContainer.is())
+ xContainer->removeContainerListener((XContainerListener*)m_pPropChangeList);
+
+ //////////////////////////////////////////////////////////////////////
+ // RootList loeschen
+ GetRootList()->clear();
+
+ //////////////////////////////////////////////////////////////////////
+ // UI benachrichtigen
+ FmNavClearedHint aClearedHint;
+ Broadcast( aClearedHint );
+ }
+
+ //------------------------------------------------------------------------
+ Reference< XNameContainer > NavigatorTreeModel::GetForms() const
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetForms" );
+ if( !m_pFormShell || !m_pFormShell->GetCurPage())
+ return NULL;
+ else
+ return m_pFormShell->GetCurPage()->GetForms();
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::Insert(FmEntryData* pEntry, ULONG nRelPos, sal_Bool bAlterModel)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Insert" );
+ if (IsListening(*m_pFormModel))
+ EndListening(*m_pFormModel);
+
+ m_pPropChangeList->Lock();
+ FmFormData* pFolder = (FmFormData*) pEntry->GetParent();
+ Reference< XChild > xElement( pEntry->GetChildIFace() );
+ if (bAlterModel)
+ {
+ XubString aStr;
+ if (pEntry->ISA(FmFormData))
+ aStr = SVX_RES(RID_STR_FORM);
+ else
+ aStr = SVX_RES(RID_STR_CONTROL);
+
+ Reference< XIndexContainer > xContainer;
+ if (pFolder)
+ xContainer = Reference< XIndexContainer > (pFolder->GetFormIface(), UNO_QUERY);
+ else
+ xContainer = Reference< XIndexContainer > (GetForms(), UNO_QUERY);
+
+ bool bUndo = m_pFormModel->IsUndoEnabled();
+
+ if( bUndo )
+ {
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT));
+ aUndoStr.SearchAndReplace('#', aStr);
+ m_pFormModel->BegUndo(aUndoStr);
+ }
+
+ if (nRelPos >= (sal_uInt32)xContainer->getCount())
+ nRelPos = (sal_uInt32)xContainer->getCount();
+
+ // UndoAction
+ if ( bUndo && m_pPropChangeList->CanUndo())
+ {
+ m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
+ FmUndoContainerAction::Inserted,
+ xContainer,
+ xElement,
+ nRelPos));
+ }
+
+ // das Element muss den Typ haben, den der Container erwartet
+ if (xContainer->getElementType() ==
+ ::getCppuType((const Reference< XForm>*)0))
+
+ {
+ Reference< XForm > xElementAsForm(xElement, UNO_QUERY);
+ xContainer->insertByIndex(nRelPos, makeAny(xElementAsForm));
+ }
+ else if (xContainer->getElementType() ==
+ ::getCppuType((const Reference< XFormComponent>*)0))
+
+ {
+ Reference< XFormComponent > xElementAsComponent(xElement, UNO_QUERY);
+ xContainer->insertByIndex(nRelPos, makeAny(xElementAsComponent));
+ }
+ else
+ {
+ DBG_ERROR("NavigatorTreeModel::Insert : the parent container needs an elementtype I don't know !");
+ }
+
+ if( bUndo )
+ m_pFormModel->EndUndo();
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Als PropertyChangeListener anmelden
+ Reference< XPropertySet > xSet(xElement, UNO_QUERY);
+ if( xSet.is() )
+ xSet->addPropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
+
+ //////////////////////////////////////////////////////////////////////
+ // Daten aus Model entfernen
+ if (pEntry->ISA(FmFormData))
+ {
+ Reference< XContainer > xContainer(xElement, UNO_QUERY);
+ if (xContainer.is())
+ xContainer->addContainerListener((XContainerListener*)m_pPropChangeList);
+ }
+
+ if (pFolder)
+ pFolder->GetChildList()->insert( pEntry, nRelPos );
+ else
+ GetRootList()->insert( pEntry, nRelPos );
+
+ //////////////////////////////////////////////////////////////////////
+ // UI benachrichtigen
+ FmNavInsertedHint aInsertedHint( pEntry, nRelPos );
+ Broadcast( aInsertedHint );
+
+ m_pPropChangeList->UnLock();
+ if (IsListening(*m_pFormModel))
+ StartListening(*m_pFormModel);
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::Remove(FmEntryData* pEntry, sal_Bool bAlterModel)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Remove" );
+ //////////////////////////////////////////////////////////////////////
+ // Form und Parent holen
+ if (!pEntry || !m_pFormModel)
+ return;
+
+ if (IsListening(*m_pFormModel))
+ EndListening(*m_pFormModel);
+
+ const bool bUndo = m_pFormModel->IsUndoEnabled();
+
+ m_pPropChangeList->Lock();
+ FmFormData* pFolder = (FmFormData*) pEntry->GetParent();
+ Reference< XChild > xElement ( pEntry->GetChildIFace() );
+ if (bAlterModel)
+ {
+ XubString aStr;
+ if (pEntry->ISA(FmFormData))
+ aStr = SVX_RES(RID_STR_FORM);
+ else
+ aStr = SVX_RES(RID_STR_CONTROL);
+
+ if( bUndo )
+ {
+ XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE));
+ aUndoStr.SearchAndReplace('#', aStr);
+ m_pFormModel->BegUndo(aUndoStr);
+ }
+ }
+
+ // jetzt die eigentliche Entfernung der Daten aus dem Model
+ if (pEntry->ISA(FmFormData))
+ RemoveForm((FmFormData*)pEntry);
+ else
+ RemoveFormComponent((FmControlData*)pEntry);
+
+
+ if (bAlterModel)
+ {
+ Reference< XIndexContainer > xContainer(xElement->getParent(), UNO_QUERY);
+ // aus dem Container entfernen
+ sal_Int32 nContainerIndex = getElementPos(xContainer.get(), xElement);
+ // UndoAction
+ if (nContainerIndex >= 0)
+ {
+ if ( bUndo && m_pPropChangeList->CanUndo())
+ {
+ m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
+ FmUndoContainerAction::Removed,
+ xContainer,
+ xElement, nContainerIndex ));
+ }
+ else if( !m_pPropChangeList->CanUndo() )
+ {
+ FmUndoContainerAction::DisposeElement( xElement );
+ }
+
+ xContainer->removeByIndex(nContainerIndex );
+ }
+
+ if( bUndo )
+ m_pFormModel->EndUndo();
+ }
+
+ // beim Vater austragen
+ if (pFolder)
+ pFolder->GetChildList()->remove( pEntry );
+ else
+ {
+ GetRootList()->remove( pEntry );
+ //////////////////////////////////////////////////////////////////////
+ // Wenn keine Form mehr in der Root, an der Shell CurForm zuruecksetzen
+ if ( !GetRootList()->size() )
+ m_pFormShell->GetImpl()->forgetCurrentForm();
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // UI benachrichtigen
+ FmNavRemovedHint aRemovedHint( pEntry );
+ Broadcast( aRemovedHint );
+
+ // Eintrag loeschen
+ delete pEntry;
+
+ m_pPropChangeList->UnLock();
+ StartListening(*m_pFormModel);
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::RemoveForm(FmFormData* pFormData)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveForm" );
+ //////////////////////////////////////////////////////////////////////
+ // Form und Parent holen
+ if (!pFormData || !m_pFormModel)
+ return;
+
+ FmEntryDataList* pChildList = pFormData->GetChildList();
+ for ( size_t i = pChildList->size(); i > 0; )
+ {
+ FmEntryData* pEntryData = pChildList->at( --i );
+
+ //////////////////////////////////////////////////////////////////////
+ // Child ist Form -> rekursiver Aufruf
+ if( pEntryData->ISA(FmFormData) )
+ RemoveForm( (FmFormData*)pEntryData);
+ else if( pEntryData->ISA(FmControlData) )
+ RemoveFormComponent((FmControlData*) pEntryData);
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Als PropertyChangeListener abmelden
+ Reference< XPropertySet > xSet( pFormData->GetPropertySet() );
+ if ( xSet.is() )
+ xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
+
+ Reference< XContainer > xContainer( pFormData->GetContainer() );
+ if (xContainer.is())
+ xContainer->removeContainerListener((XContainerListener*)m_pPropChangeList);
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::RemoveFormComponent(FmControlData* pControlData)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveFormComponent" );
+ //////////////////////////////////////////////////////////////////////
+ // Control und Parent holen
+ if (!pControlData)
+ return;
+
+ //////////////////////////////////////////////////////////////////////
+ // Als PropertyChangeListener abmelden
+ Reference< XPropertySet > xSet( pControlData->GetPropertySet() );
+ if (xSet.is())
+ xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList);
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::ClearBranch( FmFormData* pParentData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::ClearBranch" );
+ //////////////////////////////////////////////////////////////////////
+ // Alle Eintraege dieses Zweiges loeschen
+ FmEntryDataList* pChildList = pParentData->GetChildList();
+
+ for( size_t i = pChildList->size(); i > 0; )
+ {
+ FmEntryData* pChildData = pChildList->at( --i );
+ if( pChildData->ISA(FmFormData) )
+ ClearBranch( (FmFormData*)pChildData );
+
+ pChildList->remove( pChildData );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::FillBranch( FmFormData* pFormData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FillBranch" );
+ //////////////////////////////////////////////////////////////
+ // Forms aus der Root einfuegen
+ if( pFormData == NULL )
+ {
+ Reference< XIndexContainer > xForms(GetForms(), UNO_QUERY);
+ if (!xForms.is())
+ return;
+
+ Reference< XForm > xSubForm;
+ FmFormData* pSubFormData;
+ for (sal_Int32 i=0; i<xForms->getCount(); ++i)
+ {
+ DBG_ASSERT( xForms->getByIndex(i).getValueType() == ::getCppuType((const Reference< XForm>*)NULL),
+ "NavigatorTreeModel::FillBranch : the root container should supply only elements of type XForm");
+
+ xForms->getByIndex(i) >>= xSubForm;
+ pSubFormData = new FmFormData( xSubForm, m_aNormalImages, pFormData );
+ Insert( pSubFormData, LIST_APPEND );
+
+ //////////////////////////////////////////////////////////////
+ // Neuer Branch, wenn SubForm wiederum Subforms enthaelt
+ FillBranch( pSubFormData );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////
+ // Componenten einfuegen
+ else
+ {
+ Reference< XIndexContainer > xComponents( GetFormComponents(pFormData));
+ if( !xComponents.is() ) return;
+
+ ::rtl::OUString aControlName;
+ Reference< XInterface > xInterface;
+ Reference< XPropertySet > xSet;
+ FmControlData* pNewControlData;
+ FmFormData* pSubFormData;
+
+ Reference< XFormComponent > xCurrentComponent;
+ for (sal_Int32 j=0; j<xComponents->getCount(); ++j)
+ {
+ xComponents->getByIndex(j) >>= xCurrentComponent;
+ Reference< XForm > xSubForm(xCurrentComponent, UNO_QUERY);
+
+ if (xSubForm.is())
+ { // die aktuelle Component ist eine Form
+ pSubFormData = new FmFormData(xSubForm, m_aNormalImages, pFormData);
+ Insert(pSubFormData, LIST_APPEND);
+
+ //////////////////////////////////////////////////////////////
+ // Neuer Branch, wenn SubForm wiederum Subforms enthaelt
+ FillBranch(pSubFormData);
+ }
+ else
+ {
+ pNewControlData = new FmControlData(xCurrentComponent, m_aNormalImages, pFormData);
+ Insert(pNewControlData, LIST_APPEND);
+ }
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::InsertForm(const Reference< XForm > & xForm, sal_uInt32 nRelPos)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertForm" );
+ FmFormData* pFormData = (FmFormData*)FindData( xForm, GetRootList() );
+ if (pFormData)
+ return;
+
+ //////////////////////////////////////////////////////////
+ // ParentData setzen
+ Reference< XInterface > xIFace( xForm->getParent());
+ Reference< XForm > xParentForm(xIFace, UNO_QUERY);
+ FmFormData* pParentData = NULL;
+ if (xParentForm.is())
+ pParentData = (FmFormData*)FindData( xParentForm, GetRootList() );
+
+ pFormData = new FmFormData( xForm, m_aNormalImages, pParentData );
+ Insert( pFormData, nRelPos );
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::InsertFormComponent(const Reference< XFormComponent > & xComp, sal_uInt32 nRelPos)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertFormComponent" );
+ //////////////////////////////////////////////////////////
+ // ParentData setzen
+ Reference< XInterface > xIFace( xComp->getParent());
+ Reference< XForm > xForm(xIFace, UNO_QUERY);
+ if (!xForm.is())
+ return;
+
+ FmFormData* pParentData = (FmFormData*)FindData( xForm, GetRootList() );
+ if( !pParentData )
+ {
+ pParentData = new FmFormData( xForm, m_aNormalImages, NULL );
+ Insert( pParentData, LIST_APPEND );
+ }
+
+ if (!FindData(xComp, pParentData->GetChildList(),sal_False))
+ {
+ //////////////////////////////////////////////////////////
+ // Neue EntryData setzen
+ FmEntryData* pNewEntryData = new FmControlData( xComp, m_aNormalImages, pParentData );
+
+ //////////////////////////////////////////////////////////
+ // Neue EntryData einfuegen
+ Insert( pNewEntryData, nRelPos );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::ReplaceFormComponent(
+ const Reference< XFormComponent > & xOld,
+ const Reference< XFormComponent > & xNew
+ )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::ReplaceFormComponent" );
+ FmEntryData* pData = FindData(xOld, GetRootList(), sal_True);
+ DBG_ASSERT(pData && pData->ISA(FmControlData), "NavigatorTreeModel::ReplaceFormComponent : invalid argument !");
+ ((FmControlData*)pData)->ModelReplaced( xNew, m_aNormalImages );
+
+ FmNavModelReplacedHint aReplacedHint( pData );
+ Broadcast( aReplacedHint );
+ }
+
+ //------------------------------------------------------------------------
+ FmEntryData* NavigatorTreeModel::FindData(const Reference< XInterface > & xElement, FmEntryDataList* pDataList, sal_Bool bRecurs)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FindData" );
+ // normalize
+ Reference< XInterface > xIFace( xElement, UNO_QUERY );
+
+ for ( size_t i = 0; i < pDataList->size(); i++ )
+ {
+ FmEntryData* pEntryData = pDataList->at( i );
+ if ( pEntryData->GetElement().get() == xIFace.get() )
+ return pEntryData;
+ else if (bRecurs)
+ {
+ pEntryData = FindData( xElement, pEntryData->GetChildList() );
+ if (pEntryData)
+ return pEntryData;
+ }
+ }
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------
+ FmEntryData* NavigatorTreeModel::FindData( const ::rtl::OUString& rText, FmFormData* pParentData, sal_Bool bRecurs )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::FindData" );
+ FmEntryDataList* pDataList;
+ if( !pParentData )
+ pDataList = GetRootList();
+ else
+ pDataList = pParentData->GetChildList();
+
+ ::rtl::OUString aEntryText;
+ FmEntryData* pEntryData;
+ FmEntryData* pChildData;
+
+ for( size_t i = 0; i < pDataList->size(); i++ )
+ {
+ pEntryData = pDataList->at( i );
+ aEntryText = pEntryData->GetText();
+
+ if (rText == aEntryText)
+ return pEntryData;
+
+ if( bRecurs && pEntryData->ISA(FmFormData) )
+ {
+ pChildData = FindData( rText, (FmFormData*)pEntryData );
+ if( pChildData )
+ return pChildData;
+ }
+ }
+
+ return NULL;
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Notify" );
+ if( rHint.ISA(SdrHint) )
+ {
+ SdrHint* pSdrHint = (SdrHint*)&rHint;
+ switch( pSdrHint->GetKind() )
+ {
+ case HINT_OBJINSERTED:
+ InsertSdrObj(pSdrHint->GetObject());
+ break;
+ case HINT_OBJREMOVED:
+ RemoveSdrObj(pSdrHint->GetObject());
+ break;
+ default:
+ break;
+ }
+ }
+ // hat sich die shell verabschiedet?
+ else if ( rHint.ISA(SfxSimpleHint) && ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING)
+ UpdateContent((FmFormShell*)NULL);
+
+ // hat sich die Markierung der Controls veraendert ?
+ else if (rHint.ISA(FmNavViewMarksChanged))
+ {
+ FmNavViewMarksChanged* pvmcHint = (FmNavViewMarksChanged*)&rHint;
+ BroadcastMarkedObjects( pvmcHint->GetAffectedView()->GetMarkedObjectList() );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::InsertSdrObj( const SdrObject* pObj )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertSdrObj" );
+ const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
+ if ( pFormObject )
+ {
+ try
+ {
+ Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
+ Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
+
+ sal_Int32 nPos = getElementPos( xContainer, xFormComponent );
+ InsertFormComponent( xFormComponent, nPos );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ else if ( pObj->IsGroupObject() )
+ {
+ SdrObjListIter aIter( *pObj->GetSubList() );
+ while ( aIter.IsMore() )
+ InsertSdrObj( aIter.Next() );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::RemoveSdrObj( const SdrObject* pObj )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::RemoveSdrObj" );
+ const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
+ if ( pFormObject )
+ {
+ try
+ {
+ Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
+ FmEntryData* pEntryData = FindData( xFormComponent, GetRootList(), sal_True );
+ if ( pEntryData )
+ Remove( pEntryData );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ else if ( pObj->IsGroupObject() )
+ {
+ SdrObjListIter aIter( *pObj->GetSubList() );
+ while ( aIter.IsMore() )
+ RemoveSdrObj( aIter.Next() );
+ }
+ }
+
+ sal_Bool NavigatorTreeModel::InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::InsertFormComponent" );
+ if ( pObject->ISA(SdrObjGroup) )
+ { // rekursiv absteigen
+ const SdrObjList *pChilds = ((SdrObjGroup*)pObject)->GetSubList();
+ for ( sal_uInt16 i=0; i<pChilds->GetObjCount(); ++i )
+ {
+ SdrObject* pCurrent = pChilds->GetObj(i);
+ if (!InsertFormComponent(rHint, pCurrent))
+ return sal_False;
+ }
+ }
+ else
+ {
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
+ if ( !pFormObject )
+ return sal_False;
+
+ try
+ {
+ Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
+ FmEntryData* pControlData = FindData( xFormViewControl, GetRootList() );
+ if ( !pControlData )
+ return sal_False;
+
+ rHint.AddItem( pControlData );
+ return sal_True;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ return sal_False;
+ }
+ }
+
+ return sal_True;
+ }
+
+ void NavigatorTreeModel::BroadcastMarkedObjects(const SdrMarkList& mlMarked)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::BroadcastMarkedObjects" );
+ // gehen wir durch alle markierten Objekte und suchen wir die raus, mit denen ich was anfangen kann
+ FmNavRequestSelectHint rshRequestSelection;
+ sal_Bool bIsMixedSelection = sal_False;
+
+ for (ULONG i=0; (i<mlMarked.GetMarkCount()) && !bIsMixedSelection; i++)
+ {
+ SdrObject* pobjCurrent = mlMarked.GetMark(i)->GetMarkedSdrObj();
+ bIsMixedSelection |= !InsertFormComponent(rshRequestSelection, pobjCurrent);
+ // bei einem Nicht-Form-Control liefert InsertFormComponent sal_False !
+ }
+
+ rshRequestSelection.SetMixedSelection(bIsMixedSelection);
+ if (bIsMixedSelection)
+ rshRequestSelection.ClearItems();
+
+ Broadcast(rshRequestSelection);
+ // eine leere Liste interpretiert der NavigatorTree so, dass er seine Selektion komplett rausnimmt
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::UpdateContent( const Reference< XNameContainer > & xForms )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::UpdateContent" );
+ //////////////////////////////////////////////////////////////////////
+ // Model von der Root aufwaerts neu fuellen
+ Clear();
+ if (xForms.is())
+ {
+ Reference< XContainer > xFormContainer(xForms, UNO_QUERY);
+ if (xFormContainer.is())
+ xFormContainer->addContainerListener((XContainerListener*)m_pPropChangeList);
+
+ FillBranch(NULL);
+
+ // jetzt in meinem Tree genau die das in meiner View markierte Control selektieren
+ // (bzw alle solchen), falls es eines gibt ...
+ if(!m_pFormShell) return; // keine Shell -> wech
+
+ FmFormView* pFormView = m_pFormShell->GetFormView();
+ DBG_ASSERT(pFormView != NULL, "NavigatorTreeModel::UpdateContent : keine FormView");
+ BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void NavigatorTreeModel::UpdateContent( FmFormShell* pShell )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::UpdateContent" );
+ //////////////////////////////////////////////////////////////////////
+ // Wenn Shell sich nicht veraendert hat, nichts machen
+ FmFormPage* pNewPage = pShell ? pShell->GetCurPage() : NULL;
+ if ((pShell == m_pFormShell) && (m_pFormPage == pNewPage))
+ return;
+
+ //////////////////////////////////////////////////////////////////////
+ // Als Listener abmelden
+ if( m_pFormShell )
+ {
+ if (m_pFormModel)
+ EndListening( *m_pFormModel );
+ m_pFormModel = NULL;
+ EndListening( *m_pFormShell );
+ Clear();
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Vollupdate
+ m_pFormShell = pShell;
+ if (m_pFormShell)
+ {
+ m_pFormPage = pNewPage;
+ UpdateContent(m_pFormPage->GetForms());
+ } else
+ m_pFormPage = NULL;
+
+ //////////////////////////////////////////////////////////////////////
+ // Als Listener neu anmelden
+ if( m_pFormShell )
+ {
+ StartListening( *m_pFormShell );
+ m_pFormModel = m_pFormShell->GetFormModel();
+ if( m_pFormModel )
+ StartListening( *m_pFormModel );
+ }
+ }
+
+ //------------------------------------------------------------------------
+ Reference< XIndexContainer > NavigatorTreeModel::GetFormComponents( FmFormData* pFormData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetFormComponents" );
+ //////////////////////////////////////////////////////////////////////
+ // Von der Form Components holen
+ if (pFormData)
+ return Reference< XIndexContainer > (pFormData->GetFormIface(), UNO_QUERY);
+
+ return Reference< XIndexContainer > ();
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTreeModel::CheckEntry( FmEntryData* pEntryData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::CheckEntry" );
+ //////////////////////////////////////////////////////////////////////
+ // Nur Forms duerfen auf Doppeldeutigkeit untersucht werden
+ if( !pEntryData->ISA(FmFormData) ) return sal_True;
+
+ //////////////////////////////////////////////////////////////////////
+ // ChildListe des Parents holen
+ FmFormData* pParentData = (FmFormData*)pEntryData->GetParent();
+ FmEntryDataList* pChildList;
+ if( !pParentData )
+ pChildList = GetRootList();
+ else
+ pChildList = pParentData->GetChildList();
+
+ //////////////////////////////////////////////////////////////////////
+ // In ChildListe nach doppelten Namen suchen
+ ::rtl::OUString aChildText;
+ FmEntryData* pChildData;
+
+ for( size_t i = 0; i < pChildList->size(); i++ )
+ {
+ pChildData = pChildList->at( i );
+ aChildText = pChildData->GetText();
+
+ //////////////////////////////////////////////////////////////////////
+ // Gleichen Eintrag gefunden
+ if ( (aChildText == pEntryData->GetText())
+ && (pEntryData!=pChildData)
+ )
+ {
+
+
+ SQLContext aError;
+ aError.Message = String(SVX_RES(RID_ERR_CONTEXT_ADDFORM));
+ aError.Details = String(SVX_RES(RID_ERR_DUPLICATE_NAME));
+ displayException(aError);
+
+ return sal_False;
+ }
+ }
+
+ return sal_True;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTreeModel::Rename( FmEntryData* pEntryData, const ::rtl::OUString& rNewText )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Rename" );
+ //////////////////////////////////////////////////////////////////////
+ // Wenn Name schon vorhanden, Fehlermeldung
+ pEntryData->SetText( rNewText );
+
+ //////////////////////////////////////////////////////////////////////
+ // PropertySet besorgen
+ Reference< XFormComponent > xFormComponent;
+
+ if( pEntryData->ISA(FmFormData) )
+ {
+ FmFormData* pFormData = (FmFormData*)pEntryData;
+ Reference< XForm > xForm( pFormData->GetFormIface());
+ xFormComponent = Reference< XFormComponent > (xForm, UNO_QUERY);
+ }
+
+ if( pEntryData->ISA(FmControlData) )
+ {
+ FmControlData* pControlData = (FmControlData*)pEntryData;
+ xFormComponent = pControlData->GetFormComponent();
+ }
+
+ if( !xFormComponent.is() ) return sal_False;
+ Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
+ if( !xSet.is() ) return sal_False;
+
+ //////////////////////////////////////////////////////////////////////
+ // Namen setzen
+ xSet->setPropertyValue( FM_PROP_NAME, makeAny(rNewText) );
+
+ return sal_True;
+ }
+
+ //------------------------------------------------------------------------
+ sal_Bool NavigatorTreeModel::IsNameAlreadyDefined( const ::rtl::OUString& rName, FmFormData* pParentData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::IsNameAlreadyDefined" );
+ //////////////////////////////////////////////////////////////////////
+ // Form in der Root
+ if( !pParentData )
+ {
+ if (GetForms()->hasByName(rName))
+ return sal_True;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Restliche Components
+ else
+ {
+ Reference< XNameContainer > xFormComponents(GetFormComponents(pParentData), UNO_QUERY);
+ if (xFormComponents.is() && xFormComponents->hasByName(rName))
+ return sal_True;
+ }
+
+ return sal_False;
+ }
+
+ //------------------------------------------------------------------------
+ SdrObject* NavigatorTreeModel::GetSdrObj( FmControlData* pControlData )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::GetSdrObj" );
+ if (!pControlData || !m_pFormShell)
+ return NULL;
+
+ //////////////////////////////////////////////////////////////////////
+ // In der Page das entsprechende SdrObj finden und selektieren
+ Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
+ if (!xFormComponent.is())
+ return NULL;
+
+ FmFormView* pFormView = m_pFormShell->GetFormView();
+ SdrPageView* pPageView = pFormView->GetSdrPageView();
+ SdrPage* pPage = pPageView->GetPage();
+
+ SdrObjListIter aIter( *pPage );
+ return Search(aIter, xFormComponent);
+ }
+
+ //------------------------------------------------------------------
+ SdrObject* NavigatorTreeModel::Search(SdrObjListIter& rIter, const Reference< XFormComponent > & xComp)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTreeModel::Search" );
+ while (rIter.IsMore())
+ {
+ SdrObject* pObj = rIter.Next();
+ FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
+ if ( pFormObject )
+ {
+ Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY );
+ if ( xFormViewControl == xComp )
+ return pObj;
+ }
+ else if ( pObj->IsGroupObject() )
+ {
+ SdrObjListIter aIter( *pObj->GetSubList() );
+ pObj = Search( aIter, xComp );
+ if ( pObj )
+ return pObj;
+ }
+ }
+ return NULL;
+ }
+
+//............................................................................
+} // namespace svxform
+//............................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/sdbdatacolumn.cxx b/svx/source/form/sdbdatacolumn.cxx
new file mode 100644
index 000000000000..120c8f8bb41d
--- /dev/null
+++ b/svx/source/form/sdbdatacolumn.cxx
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "sdbdatacolumn.hxx"
+
+//..............................................................................
+namespace svxform
+{
+//..............................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::io;
+ using namespace ::com::sun::star::container;
+
+ //==========================================================================
+ //= DataColumn - a class wrapping an object implementing a sdb::DataColumn service
+ //==========================================================================
+ DataColumn::DataColumn(const Reference< ::com::sun::star::beans::XPropertySet>& _rxIFace)
+ {
+ m_xPropertySet = _rxIFace;
+ m_xColumn = Reference< ::com::sun::star::sdb::XColumn>(_rxIFace, UNO_QUERY);
+ m_xColumnUpdate = Reference< ::com::sun::star::sdb::XColumnUpdate>(_rxIFace, UNO_QUERY);
+
+ if (!m_xPropertySet.is() || !m_xColumn.is())
+ {
+ m_xPropertySet = NULL;
+ m_xColumn = NULL;
+ m_xColumnUpdate = NULL;
+ }
+ }
+
+ // Reference< XPropertySet>
+ Reference< XPropertySetInfo> DataColumn::getPropertySetInfo() const throw( RuntimeException )
+ {
+ return m_xPropertySet->getPropertySetInfo();
+ }
+
+ void DataColumn::setPropertyValue(const ::rtl::OUString& aPropertyName, const Any& aValue) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
+ {
+ m_xPropertySet->setPropertyValue(aPropertyName, aValue);
+ }
+
+ Any DataColumn::getPropertyValue(const ::rtl::OUString& PropertyName) const throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+ {
+ return m_xPropertySet->getPropertyValue(PropertyName);
+ }
+
+ void DataColumn::addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener>& xListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+ {
+ m_xPropertySet->addPropertyChangeListener(aPropertyName, xListener);
+ }
+
+ void DataColumn::removePropertyChangeListener(const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener>& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+ {
+ m_xPropertySet->removePropertyChangeListener(aPropertyName, aListener);
+ }
+
+ void DataColumn::addVetoableChangeListener(const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener>& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+ {
+ m_xPropertySet->addVetoableChangeListener(PropertyName, aListener);
+ }
+
+ void DataColumn::removeVetoableChangeListener(const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener>& aListener) throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+ {
+ m_xPropertySet->removeVetoableChangeListener(PropertyName, aListener);
+ }
+
+ // XColumn
+ sal_Bool DataColumn::wasNull() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->wasNull();
+ }
+
+ ::rtl::OUString DataColumn::getString() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getString();
+ }
+
+ sal_Bool DataColumn::getBoolean() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getBoolean();
+ }
+
+ sal_Int8 DataColumn::getByte() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getByte();
+ }
+
+ sal_Int16 DataColumn::getShort() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getShort();
+ }
+
+ sal_Int32 DataColumn::getInt() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getInt();
+ }
+
+ sal_Int64 DataColumn::getLong() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getLong();
+ }
+
+ float DataColumn::getFloat() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getFloat();
+ }
+
+ double DataColumn::getDouble() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getDouble();
+ }
+
+ Sequence< sal_Int8 > DataColumn::getBytes() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getBytes();
+ }
+
+ com::sun::star::util::Date DataColumn::getDate() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getDate();
+ }
+
+ com::sun::star::util::Time DataColumn::getTime() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getTime();
+ }
+
+ com::sun::star::util::DateTime DataColumn::getTimestamp() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getTimestamp();
+ }
+
+ Reference< XInputStream> DataColumn::getBinaryStream() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getBinaryStream();
+ }
+
+ Reference< XInputStream> DataColumn::getCharacterStream() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getCharacterStream();
+ }
+
+ Any DataColumn::getObject(const Reference< XNameAccess>& typeMap) throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getObject(typeMap);
+ }
+
+ Reference< XRef> DataColumn::getRef() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getRef();
+ }
+
+ Reference< XBlob> DataColumn::getBlob() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getBlob();
+ }
+
+ Reference< XClob> DataColumn::getClob() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getClob();
+ }
+
+ Reference< XArray> DataColumn::getArray() throw( SQLException, RuntimeException )
+ {
+ return m_xColumn->getArray();
+ }
+
+ // XColumnUpdate
+ void DataColumn::updateNull() throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateNull();
+ }
+
+ void DataColumn::updateBoolean(sal_Bool x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateBoolean(x);
+ }
+
+ void DataColumn::updateByte(sal_Int8 x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateByte(x);
+ }
+
+ void DataColumn::updateShort(sal_Int16 x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateShort(x);
+ }
+
+ void DataColumn::updateInt(sal_Int32 x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateInt(x);
+ }
+
+ void DataColumn::updateLong(sal_Int64 x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateLong(x);
+ }
+
+ void DataColumn::updateFloat(float x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateFloat(x);
+ }
+
+ void DataColumn::updateDouble(double x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateDouble(x);
+ }
+
+ void DataColumn::updateString(const ::rtl::OUString& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateString(x);
+ }
+
+ void DataColumn::updateBytes(const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateBytes(x);
+ }
+
+ void DataColumn::updateDate(const com::sun::star::util::Date& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateDate(x);
+ }
+
+ void DataColumn::updateTime(const com::sun::star::util::Time& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateTime(x);
+ }
+
+ void DataColumn::updateTimestamp(const com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateTimestamp(x);
+ }
+
+ void DataColumn::updateBinaryStream(const Reference< XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateBinaryStream(x, length);
+ }
+
+ void DataColumn::updateCharacterStream(const Reference< XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateCharacterStream(x, length);
+ }
+
+ void DataColumn::updateObject(const Any& x) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateObject(x);
+ }
+
+ void DataColumn::updateNumericObject(const Any& x, sal_Int32 scale) throw( SQLException, RuntimeException )
+ {
+ m_xColumnUpdate->updateNumericObject(x, scale);
+ }
+
+ //..............................................................................
+} // namespace svxform
+//..............................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/sqlparserclient.cxx b/svx/source/form/sqlparserclient.cxx
new file mode 100644
index 000000000000..3c1b786e9659
--- /dev/null
+++ b/svx/source/form/sqlparserclient.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "sqlparserclient.hxx"
+#include "ParseContext.hxx"
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+
+ //====================================================================
+ //= OSQLParserClient
+ //====================================================================
+ //--------------------------------------------------------------------
+ OSQLParserClient::OSQLParserClient(const Reference< XMultiServiceFactory >& _rxORB)
+ {
+ m_xORB = _rxORB;
+ }
+ //--------------------------------------------------------------------
+ bool OSQLParserClient::ensureLoaded() const
+ {
+ if ( !ODbtoolsClient::ensureLoaded() )
+ return false;
+ m_xParser = getFactory()->createSQLParser(m_xORB,getParseContext());
+ return m_xParser.is();
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/stringlistresource.cxx b/svx/source/form/stringlistresource.cxx
new file mode 100644
index 000000000000..83d6274d1e5d
--- /dev/null
+++ b/svx/source/form/stringlistresource.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "stringlistresource.hxx"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+
+#include <tools/rcid.h>
+
+//........................................................................
+namespace svx
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ /** === end UNO using === **/
+
+ //====================================================================
+ //= StringListResource
+ //====================================================================
+ //--------------------------------------------------------------------
+ StringListResource::StringListResource( const ResId& _rResId )
+ :Resource( _rResId )
+ {
+ USHORT nLocalID = 1;
+ ResId aLocalID( nLocalID, *_rResId.GetResMgr() );
+ while ( IsAvailableRes( aLocalID.SetRT( RSC_STRING ) ) )
+ {
+ String sLocalString( aLocalID );
+ m_aStrings.push_back( sLocalString );
+ aLocalID = ResId( ++nLocalID, *_rResId.GetResMgr() );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ StringListResource::~StringListResource()
+ {
+ FreeResource();
+ }
+
+//........................................................................
+} // namespace svx
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/tabwin.cxx b/svx/source/form/tabwin.cxx
new file mode 100644
index 000000000000..5c8ddbd0f662
--- /dev/null
+++ b/svx/source/form/tabwin.cxx
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "tabwin.hxx"
+#include "svx/fmtools.hxx"
+#include "fmservs.hxx"
+#include "stringlistresource.hxx"
+
+#include <svx/svxids.hrc>
+#include <svx/dbaexchange.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/util/XLocalizedAliases.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/stl_types.hxx>
+
+#include "fmhelp.hrc"
+#include <svx/fmshell.hxx>
+#include "fmshimp.hxx"
+#include "svx/dbtoolsclient.hxx"
+#include <svx/fmpage.hxx>
+
+#include "fmpgeimp.hxx"
+
+#include "fmprop.hrc"
+
+#include "fmresids.hrc"
+#include <svx/dialmgr.hxx>
+#include <tools/shl.hxx>
+#include <svx/svdpagv.hxx>
+#include <sfx2/objitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <comphelper/property.hxx>
+#include <sfx2/frame.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+
+const long STD_WIN_POS_X = 50;
+const long STD_WIN_POS_Y = 50;
+
+const long STD_WIN_SIZE_X = 120;
+const long STD_WIN_SIZE_Y = 150;
+
+const long MIN_WIN_SIZE_X = 50;
+const long MIN_WIN_SIZE_Y = 50;
+
+const long LISTBOX_BORDER = 2;
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star;
+using namespace ::svxform;
+using namespace ::svx;
+
+
+struct ColumnInfo
+{
+ ::rtl::OUString sColumnName;
+ ::rtl::OUString sLabel;
+ bool bColumn;
+ ColumnInfo(const ::rtl::OUString& i_sColumnName,const ::rtl::OUString& i_sLabel)
+ : sColumnName(i_sColumnName)
+ , sLabel(i_sLabel)
+ , bColumn(true)
+ {
+ }
+ ColumnInfo(const ::rtl::OUString& i_sColumnName)
+ : sColumnName(i_sColumnName)
+ , bColumn(false)
+ {
+ }
+};
+
+void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< container::XNameAccess>& i_xColumns )
+{
+ uno::Sequence< ::rtl::OUString > aEntries = i_xColumns->getElementNames();
+ const ::rtl::OUString* pEntries = aEntries.getConstArray();
+ sal_Int32 nEntries = aEntries.getLength();
+ for ( sal_Int32 i = 0; i < nEntries; ++i, ++pEntries )
+ {
+ uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(*pEntries),UNO_QUERY_THROW);
+ ::rtl::OUString sLabel;
+ if ( xColumn->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) )
+ xColumn->getPropertyValue(FM_PROP_LABEL) >>= sLabel;
+ if ( sLabel.getLength() )
+ _rListBox.InsertEntry( sLabel,NULL,FALSE,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) );
+ else
+ _rListBox.InsertEntry( *pEntries,NULL,FALSE,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) );
+ }
+}
+//==================================================================
+// class FmFieldWinListBox
+//==================================================================
+DBG_NAME(FmFieldWinListBox)
+//------------------------------------------------------------------------------
+FmFieldWinListBox::FmFieldWinListBox( FmFieldWin* pParent )
+ :SvTreeListBox( pParent, WB_HASBUTTONS|WB_BORDER )
+ ,pTabWin( pParent )
+{
+ DBG_CTOR(FmFieldWinListBox,NULL);
+ SetHelpId( HID_FIELD_SEL );
+
+ SetHighlightRange( );
+}
+
+//------------------------------------------------------------------------------
+FmFieldWinListBox::~FmFieldWinListBox()
+{
+ DBG_DTOR(FmFieldWinListBox,NULL);
+}
+
+//------------------------------------------------------------------------------
+sal_Int8 FmFieldWinListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
+{
+ return DND_ACTION_NONE;
+}
+
+//------------------------------------------------------------------------------
+sal_Int8 FmFieldWinListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
+{
+ return DND_ACTION_NONE;
+}
+
+//------------------------------------------------------------------------------
+BOOL FmFieldWinListBox::DoubleClickHdl()
+{
+ if ( pTabWin->createSelectionControls() )
+ return sal_True;
+
+ return SvTreeListBox::DoubleClickHdl();
+}
+
+//------------------------------------------------------------------------------
+void FmFieldWinListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
+{
+ SvLBoxEntry* pSelected = FirstSelected();
+ if (!pSelected)
+ // no drag without a field
+ return;
+
+ ::svx::ODataAccessDescriptor aDescriptor;
+ aDescriptor[ daDataSource ] <<= pTabWin->GetDatabaseName();
+ aDescriptor[ daConnection ] <<= pTabWin->GetConnection().getTyped();
+ aDescriptor[ daCommand ] <<= pTabWin->GetObjectName();
+ aDescriptor[ daCommandType ]<<= pTabWin->GetObjectType();
+ ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
+ aDescriptor[ daColumnName ] <<= pInfo->sColumnName;
+
+ TransferableHelper* pTransferColumn = new OColumnTransferable(
+ aDescriptor, CTF_FIELD_DESCRIPTOR | CTF_CONTROL_EXCHANGE | CTF_COLUMN_DESCRIPTOR
+ );
+ Reference< XTransferable> xEnsureDelete = pTransferColumn;
+ if (pTransferColumn)
+ {
+ EndSelection();
+ pTransferColumn->StartDrag( this, DND_ACTION_COPY );
+ }
+}
+
+//========================================================================
+// class FmFieldWinData
+//========================================================================
+DBG_NAME(FmFieldWinData);
+//-----------------------------------------------------------------------
+FmFieldWinData::FmFieldWinData()
+{
+ DBG_CTOR(FmFieldWinData,NULL);
+}
+
+//-----------------------------------------------------------------------
+FmFieldWinData::~FmFieldWinData()
+{
+ DBG_DTOR(FmFieldWinData,NULL);
+}
+
+//========================================================================
+// class FmFieldWin
+//========================================================================
+DBG_NAME(FmFieldWin);
+//-----------------------------------------------------------------------
+FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, Window* _pParent)
+ :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE))
+ ,SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings)
+ ,::comphelper::OPropertyChangeListener(m_aMutex)
+ ,pData(new FmFieldWinData)
+ ,m_nObjectType(0)
+ ,m_pChangeListener(NULL)
+{
+ DBG_CTOR(FmFieldWin,NULL);
+ SetHelpId( HID_FIELD_SEL_WIN );
+
+ SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
+ pListBox = new FmFieldWinListBox( this );
+ pListBox->Show();
+ UpdateContent(NULL);
+ SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y));
+}
+
+//-----------------------------------------------------------------------
+FmFieldWin::~FmFieldWin()
+{
+ if (m_pChangeListener)
+ {
+ m_pChangeListener->dispose();
+ m_pChangeListener->release();
+ // delete m_pChangeListener;
+ }
+ delete pListBox;
+ delete pData;
+ DBG_DTOR(FmFieldWin,NULL);
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::GetFocus()
+{
+ if ( pListBox )
+ pListBox->GrabFocus();
+ else
+ SfxFloatingWindow::GetFocus();
+}
+
+//-----------------------------------------------------------------------
+sal_Bool FmFieldWin::createSelectionControls( )
+{
+ SvLBoxEntry* pSelected = pListBox->FirstSelected();
+ if ( pSelected )
+ {
+ // build a descriptor for the currently selected field
+ ODataAccessDescriptor aDescr;
+ aDescr.setDataSource(GetDatabaseName());
+
+ aDescr[ daConnection ] <<= GetConnection().getTyped();
+
+ aDescr[ daCommand ] <<= GetObjectName();
+ aDescr[ daCommandType ] <<= GetObjectType();
+ ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
+ aDescr[ daColumnName ] <<= pInfo->sColumnName;//::rtl::OUString( pListBox->GetEntryText( pSelected) );
+
+ // transfer this to the SFX world
+ SfxUnoAnyItem aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR, makeAny( aDescr.createPropertyValueSequence() ) );
+ const SfxPoolItem* pArgs[] =
+ {
+ &aDescriptorItem, NULL
+ };
+
+ // execute the create slot
+ GetBindings().Execute( SID_FM_CREATE_FIELDCONTROL, pArgs );
+ }
+
+ return NULL != pSelected;
+}
+
+//-----------------------------------------------------------------------
+long FmFieldWin::PreNotify( NotifyEvent& _rNEvt )
+{
+ if ( EVENT_KEYINPUT == _rNEvt.GetType() )
+ {
+ const KeyCode& rKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
+ if ( ( 0 == rKeyCode.GetModifier() ) && ( KEY_RETURN == rKeyCode.GetCode() ) )
+ {
+ if ( createSelectionControls() )
+ return 1;
+ }
+ }
+
+ return SfxFloatingWindow::PreNotify( _rNEvt );
+}
+
+//-----------------------------------------------------------------------
+sal_Bool FmFieldWin::Close()
+{
+ return SfxFloatingWindow::Close();
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::_propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw( ::com::sun::star::uno::RuntimeException )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(evt.Source, ::com::sun::star::uno::UNO_QUERY);
+ UpdateContent(xForm);
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
+{
+ if (!pState || SID_FM_FIELDS_CONTROL != nSID)
+ return;
+
+ if (eState >= SFX_ITEM_AVAILABLE)
+ {
+ FmFormShell* pShell = PTR_CAST(FmFormShell,((SfxObjectItem*)pState)->GetShell());
+ UpdateContent(pShell);
+ }
+ else
+ UpdateContent(NULL);
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::UpdateContent(FmFormShell* pShell)
+{
+ pListBox->Clear();
+ String aTitle( SVX_RES( RID_STR_FIELDSELECTION ) );
+ SetText( aTitle );
+
+ if (!pShell || !pShell->GetImpl())
+ return;
+
+ Reference< XForm > xForm = pShell->GetImpl()->getCurrentForm();
+ if ( xForm.is() )
+ UpdateContent( xForm );
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::UpdateContent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > & xForm)
+{
+ try
+ {
+ // ListBox loeschen
+ pListBox->Clear();
+ UniString aTitle(SVX_RES(RID_STR_FIELDSELECTION));
+ SetText(aTitle);
+
+ if (!xForm.is())
+ return;
+
+ Reference< XPreparedStatement > xStatement;
+ Reference< XPropertySet > xSet(xForm, UNO_QUERY);
+
+ m_aObjectName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_COMMAND));
+ m_aDatabaseName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_DATASOURCE));
+ m_nObjectType = ::comphelper::getINT32(xSet->getPropertyValue(FM_PROP_COMMANDTYPE));
+
+ // get the connection of the form
+ OStaticDataAccessTools aTools;
+ m_aConnection.reset(
+ aTools.connectRowset( Reference< XRowSet >( xForm, UNO_QUERY ), ::comphelper::getProcessServiceFactory(), sal_True ),
+ SharedConnection::NoTakeOwnership
+ );
+ // TODO: When incompatible changes (such as extending the "virtualdbtools" interface by ensureRowSetConnection)
+ // are allowed, again, we should change this: dbtools should consistently use SharedConnection all over
+ // the place, and connectRowset should be replaced with ensureRowSetConnection
+
+ // get the fields of the object
+
+ if ( m_aConnection.is() && m_aObjectName.getLength() )
+ {
+ Reference< XComponent > xKeepFieldsAlive;
+ Reference< XNameAccess > xColumns = getFieldsByCommandDescriptor( m_aConnection, m_nObjectType, m_aObjectName,xKeepFieldsAlive );
+ if ( xColumns.is() )
+ lcl_addToList(*pListBox,xColumns);
+ }
+
+ // Prefix setzen
+ UniString aPrefix;
+ StringListResource aPrefixes( SVX_RES( RID_RSC_TABWIN_PREFIX ) );
+
+ switch (m_nObjectType)
+ {
+ case CommandType::TABLE:
+ aPrefix = aPrefixes[0];
+ break;
+ case CommandType::QUERY:
+ aPrefix = aPrefixes[1];
+ break;
+ default:
+ aPrefix = aPrefixes[2];
+ break;
+ }
+
+ // an dem PropertySet nach Aenderungen der ControlSource lauschen
+ if (m_pChangeListener)
+ {
+ m_pChangeListener->dispose();
+ m_pChangeListener->release();
+ }
+ m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet);
+ m_pChangeListener->acquire();
+ m_pChangeListener->addProperty(FM_PROP_DATASOURCE);
+ m_pChangeListener->addProperty(FM_PROP_COMMAND);
+ m_pChangeListener->addProperty(FM_PROP_COMMANDTYPE);
+
+ // Titel setzen
+ aTitle.AppendAscii(" ");
+ aTitle += aPrefix;
+ aTitle.AppendAscii(" ");
+ aTitle += m_aObjectName.getStr();
+ SetText( aTitle );
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "FmTabWin::UpdateContent: caught an exception!" );
+ }
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::Resize()
+{
+ SfxFloatingWindow::Resize();
+
+ Point aPos(GetPosPixel());
+ Size aOutputSize( GetOutputSizePixel() );
+
+ //////////////////////////////////////////////////////////////////////
+
+ // Groesse der ::com::sun::star::form::ListBox anpassen
+ Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER );
+ Size aLBSize( aOutputSize );
+ aLBSize.Width() -= (2*LISTBOX_BORDER);
+ aLBSize.Height() -= (2*LISTBOX_BORDER);
+
+ pListBox->SetPosSizePixel( aLBPos, aLBSize );
+}
+
+//-----------------------------------------------------------------------
+void FmFieldWin::FillInfo( SfxChildWinInfo& rInfo ) const
+{
+ rInfo.bVisible = sal_False;
+}
+
+//-----------------------------------------------------------------------
+SFX_IMPL_FLOATINGWINDOW(FmFieldWinMgr, SID_FM_ADD_FIELD)
+
+//-----------------------------------------------------------------------
+FmFieldWinMgr::FmFieldWinMgr(Window* _pParent, sal_uInt16 _nId,
+ SfxBindings* _pBindings, SfxChildWinInfo* _pInfo)
+ :SfxChildWindow(_pParent, _nId)
+{
+ pWindow = new FmFieldWin(_pBindings, this, _pParent);
+ SetHideNotDelete(sal_True);
+ eChildAlignment = SFX_ALIGN_NOALIGNMENT;
+ ((SfxFloatingWindow*)pWindow)->Initialize( _pInfo );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/tbxform.cxx b/svx/source/form/tbxform.cxx
new file mode 100644
index 000000000000..96c37148b166
--- /dev/null
+++ b/svx/source/form/tbxform.cxx
@@ -0,0 +1,469 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <string> // HACK: prevent conflict between STLPORT and Workshop headers
+#include <tools/ref.hxx>
+#include <tools/shl.hxx>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/fixed.hxx>
+#include "fmitems.hxx"
+#include "formtoolbars.hxx"
+
+
+#include <vcl/sound.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/dialogs.hrc>
+#include "tbxctl.hxx"
+#include "tbxdraw.hxx"
+#include "tbxform.hxx"
+#include "fmresids.hrc"
+#include "fmitems.hxx"
+#include "fmhelp.hrc"
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/imagemgr.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using ::com::sun::star::beans::XPropertySet;
+
+
+//========================================================================
+// class SvxFmAbsRecWin
+//========================================================================
+
+// -----------------------------------------------------------------------
+SvxFmAbsRecWin::SvxFmAbsRecWin( Window* _pParent, SfxToolBoxControl* _pController )
+ :NumericField( _pParent, WB_BORDER )
+ ,m_pController(_pController)
+{
+ SetMin(1);
+ SetFirst(1);
+ SetSpinSize(1);
+ SetSizePixel( Size(70,19) );
+
+ SetDecimalDigits(0);
+ SetStrictFormat(TRUE);
+}
+
+// -----------------------------------------------------------------------
+SvxFmAbsRecWin::~SvxFmAbsRecWin()
+{
+}
+
+// -----------------------------------------------------------------------
+void SvxFmAbsRecWin::FirePosition( sal_Bool _bForce )
+{
+ if ( _bForce || ( GetText() != GetSavedValue() ) )
+ {
+ sal_Int64 nRecord = GetValue();
+ if (nRecord < GetMin() || nRecord > GetMax())
+ {
+ Sound::Beep();
+ return;
+ }
+
+ SfxInt32Item aPositionParam( FN_PARAM_1, static_cast<INT32>(nRecord) );
+
+ Any a;
+ Sequence< PropertyValue > aArgs( 1 );
+ aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Position" ));
+ aPositionParam.QueryValue( a );
+ aArgs[0].Value = a;
+ m_pController->Dispatch( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:AbsoluteRecord" )),
+ aArgs );
+ m_pController->updateStatus();
+
+ SaveValue();
+ }
+}
+
+// -----------------------------------------------------------------------
+void SvxFmAbsRecWin::LoseFocus()
+{
+ FirePosition( sal_False );
+}
+
+// -----------------------------------------------------------------------
+void SvxFmAbsRecWin::KeyInput( const KeyEvent& rKeyEvent )
+{
+ if( rKeyEvent.GetKeyCode() == KEY_RETURN && GetText().Len() )
+ FirePosition( sal_True );
+ else
+ NumericField::KeyInput( rKeyEvent );
+}
+
+//========================================================================
+// class SvxFmTbxCtlConfig
+//========================================================================
+
+struct MapSlotToCmd
+{
+ USHORT nSlotId;
+ const char* pCommand;
+};
+
+static MapSlotToCmd SlotToCommands[] =
+{
+ { SID_FM_PUSHBUTTON, ".uno:Pushbutton" },
+ { SID_FM_RADIOBUTTON, ".uno:RadioButton" },
+ { SID_FM_CHECKBOX, ".uno:CheckBox" },
+ { SID_FM_FIXEDTEXT, ".uno:Label" },
+ { SID_FM_GROUPBOX, ".uno:GroupBox" },
+ { SID_FM_LISTBOX, ".uno:ListBox" },
+ { SID_FM_COMBOBOX, ".uno:ComboBox" },
+ { SID_FM_EDIT, ".uno:Edit" },
+ { SID_FM_DBGRID, ".uno:Grid" },
+ { SID_FM_IMAGEBUTTON, ".uno:Imagebutton" },
+ { SID_FM_IMAGECONTROL, ".uno:ImageControl" },
+ { SID_FM_FILECONTROL, ".uno:FileControl" },
+ { SID_FM_DATEFIELD, ".uno:DateField" },
+ { SID_FM_TIMEFIELD, ".uno:TimeField" },
+ { SID_FM_NUMERICFIELD, ".uno:NumericField" },
+ { SID_FM_CURRENCYFIELD, ".uno:CurrencyField" },
+ { SID_FM_PATTERNFIELD, ".uno:PatternField" },
+ { SID_FM_DESIGN_MODE, ".uno:SwitchControlDesignMode" },
+ { SID_FM_FORMATTEDFIELD, ".uno:FormattedField" },
+ { SID_FM_SCROLLBAR, ".uno:ScrollBar" },
+ { SID_FM_SPINBUTTON, ".uno:SpinButton" },
+ { 0, "" }
+};
+
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxCtlConfig, SfxUInt16Item );
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlConfig::SvxFmTbxCtlConfig( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ : SfxToolBoxControl( nSlotId, nId, rTbx )
+ ,nLastSlot( 0 )
+{
+ rTbx.SetItemBits( nId, TIB_DROPDOWN | rTbx.GetItemBits( nId ) );
+}
+
+//-----------------------------------------------------------------------
+void SvxFmTbxCtlConfig::StateChanged(USHORT nSID, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if (nSID == SID_FM_CONFIG)
+ {
+ UINT16 nSlot = 0;
+ if (eState >= SFX_ITEM_AVAILABLE)
+ nSlot = ((SfxUInt16Item*)pState)->GetValue();
+
+ switch( nSlot )
+ {
+ case SID_FM_PUSHBUTTON:
+ case SID_FM_RADIOBUTTON:
+ case SID_FM_CHECKBOX:
+ case SID_FM_FIXEDTEXT:
+ case SID_FM_GROUPBOX:
+ case SID_FM_LISTBOX:
+ case SID_FM_COMBOBOX:
+ case SID_FM_NAVIGATIONBAR:
+ case SID_FM_EDIT:
+ case SID_FM_DBGRID:
+ case SID_FM_IMAGEBUTTON:
+ case SID_FM_IMAGECONTROL:
+ case SID_FM_FILECONTROL:
+ case SID_FM_DATEFIELD:
+ case SID_FM_TIMEFIELD:
+ case SID_FM_NUMERICFIELD:
+ case SID_FM_CURRENCYFIELD:
+ case SID_FM_PATTERNFIELD:
+ case SID_FM_DESIGN_MODE:
+ case SID_FM_FORMATTEDFIELD:
+ case SID_FM_SCROLLBAR:
+ case SID_FM_SPINBUTTON:
+ { // set a new image, matching to this slot
+ rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
+ aSlotURL += rtl::OUString::valueOf( sal_Int32( nSlot ));
+ Image aImage = GetImage( m_xFrame, aSlotURL, hasBigImages() );
+ GetToolBox().SetItemImage( GetId(), aImage );
+ nLastSlot = nSlot;
+ }
+ break;
+ }
+ }
+ SfxToolBoxControl::StateChanged( nSID, eState,pState );
+}
+
+//-----------------------------------------------------------------------
+SfxPopupWindowType SvxFmTbxCtlConfig::GetPopupWindowType() const
+{
+ return( nLastSlot == 0 ? SFX_POPUPWINDOW_ONCLICK : SFX_POPUPWINDOW_ONTIMEOUT );
+}
+
+//-----------------------------------------------------------------------
+SfxPopupWindow* SvxFmTbxCtlConfig::CreatePopupWindow()
+{
+ if ( GetSlotId() == SID_FM_CONFIG )
+ {
+ ::svxform::FormToolboxes aToolboxes( m_xFrame );
+ createAndPositionSubToolBar( aToolboxes.getToolboxResourceName( SID_FM_CONFIG ) );
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------
+void SvxFmTbxCtlConfig::Select( USHORT /*nModifier*/ )
+{
+ //////////////////////////////////////////////////////////////////////
+ // Click auf den Button SID_FM_CONFIG in der ObjectBar
+ if ( nLastSlot )
+ {
+ USHORT n = 0;
+ while( SlotToCommands[n].nSlotId > 0 )
+ {
+ if ( SlotToCommands[n].nSlotId == nLastSlot )
+ break;
+ n++;
+ }
+
+ if ( SlotToCommands[n].nSlotId > 0 )
+ {
+ Sequence< PropertyValue > aArgs;
+ Dispatch( rtl::OUString::createFromAscii( SlotToCommands[n].pCommand ),
+ aArgs );
+ }
+ }
+}
+
+
+//========================================================================
+// class SvxFmTbxCtlAbsRec
+//========================================================================
+
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxCtlAbsRec, SfxInt32Item );
+DBG_NAME(SvxFmTbxCtlAbsRec);
+//-----------------------------------------------------------------------
+SvxFmTbxCtlAbsRec::SvxFmTbxCtlAbsRec( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ DBG_CTOR(SvxFmTbxCtlAbsRec,NULL);
+}
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlAbsRec::~SvxFmTbxCtlAbsRec()
+{
+ DBG_DTOR(SvxFmTbxCtlAbsRec,NULL);
+}
+
+//-----------------------------------------------------------------------
+void SvxFmTbxCtlAbsRec::StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState )
+{
+ USHORT nId = GetId();
+ ToolBox* pToolBox = &GetToolBox();
+ SvxFmAbsRecWin* pWin = (SvxFmAbsRecWin*)( pToolBox->GetItemWindow(nId) );
+
+ DBG_ASSERT( pWin, "Control not found!" );
+
+ if (pState)
+ {
+ const SfxInt32Item* pItem = PTR_CAST( SfxInt32Item, pState );
+ DBG_ASSERT( pItem, "SvxFmTbxCtlAbsRec::StateChanged: invalid item!" );
+ pWin->SetValue( pItem ? pItem->GetValue() : -1 );
+ }
+
+ BOOL bEnable = SFX_ITEM_DISABLED != eState && pState;
+ if (!bEnable)
+ pWin->SetText(String());
+
+ //////////////////////////////////////////////////////////////////////
+ // Enablen/disablen des Fensters
+ pToolBox->EnableItem(nId, bEnable);
+ SfxToolBoxControl::StateChanged( nSID, eState,pState );
+}
+
+//-----------------------------------------------------------------------
+Window* SvxFmTbxCtlAbsRec::CreateItemWindow( Window* pParent )
+{
+ SvxFmAbsRecWin* pWin = new SvxFmAbsRecWin( pParent, this );
+ pWin->SetUniqueId( UID_ABSOLUTE_RECORD_WINDOW );
+ return pWin;
+}
+
+
+//========================================================================
+// SvxFmTbxCtlRecText
+//========================================================================
+
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxCtlRecText, SfxBoolItem );
+DBG_NAME(SvxFmTbxCtlRecText);
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecText::SvxFmTbxCtlRecText( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ DBG_CTOR(SvxFmTbxCtlRecText,NULL);
+}
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecText::~SvxFmTbxCtlRecText()
+{
+ DBG_DTOR(SvxFmTbxCtlRecText,NULL);
+}
+
+//-----------------------------------------------------------------------
+Window* SvxFmTbxCtlRecText::CreateItemWindow( Window* pParent )
+{
+ XubString aText( SVX_RES(RID_STR_REC_TEXT) );
+ FixedText* pFixedText = new FixedText( pParent );
+ Size aSize( pFixedText->GetTextWidth( aText ), pFixedText->GetTextHeight( ) );
+ pFixedText->SetText( aText );
+ aSize.Width() += 6;
+ pFixedText->SetSizePixel( aSize );
+ pFixedText->SetBackground(Wallpaper(Color(COL_TRANSPARENT)));
+
+ return pFixedText;
+}
+
+
+//========================================================================
+// SvxFmTbxCtlRecFromText
+//========================================================================
+
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxCtlRecFromText, SfxBoolItem );
+DBG_NAME(SvxFmTbxCtlRecFromText);
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecFromText::SvxFmTbxCtlRecFromText( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ DBG_CTOR(SvxFmTbxCtlRecFromText,NULL);
+}
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecFromText::~SvxFmTbxCtlRecFromText()
+{
+ DBG_DTOR(SvxFmTbxCtlRecFromText,NULL);
+}
+
+//-----------------------------------------------------------------------
+Window* SvxFmTbxCtlRecFromText::CreateItemWindow( Window* pParent )
+{
+ XubString aText( SVX_RES(RID_STR_REC_FROM_TEXT) );
+ FixedText* pFixedText = new FixedText( pParent, WB_CENTER );
+ Size aSize( pFixedText->GetTextWidth( aText ), pFixedText->GetTextHeight( ) );
+ aSize.Width() += 12;
+ pFixedText->SetText( aText );
+ pFixedText->SetSizePixel( aSize );
+ pFixedText->SetBackground(Wallpaper(Color(COL_TRANSPARENT)));
+ return pFixedText;
+}
+
+
+//========================================================================
+// SvxFmTbxCtlRecTotal
+//========================================================================
+DBG_NAME(SvxFmTbxCtlRecTotal);
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxCtlRecTotal, SfxStringItem );
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecTotal::SvxFmTbxCtlRecTotal( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+ ,pFixedText( NULL )
+{
+ DBG_CTOR(SvxFmTbxCtlRecTotal,NULL);
+}
+
+//-----------------------------------------------------------------------
+SvxFmTbxCtlRecTotal::~SvxFmTbxCtlRecTotal()
+{
+ DBG_DTOR(SvxFmTbxCtlRecTotal,NULL);
+}
+
+//-----------------------------------------------------------------------
+Window* SvxFmTbxCtlRecTotal::CreateItemWindow( Window* pParent )
+{
+ pFixedText = new FixedText( pParent );
+ String aSample(RTL_CONSTASCII_USTRINGPARAM("123456"));
+ Size aSize( pFixedText->GetTextWidth( aSample ), pFixedText->GetTextHeight( ) );
+ aSize.Width() += 12;
+ pFixedText->SetSizePixel( aSize );
+ pFixedText->SetBackground();
+ pFixedText->SetPaintTransparent(TRUE);
+ return pFixedText;
+}
+
+//-----------------------------------------------------------------------
+void SvxFmTbxCtlRecTotal::StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState )
+{
+ //////////////////////////////////////////////////////////////////////
+ // Setzen des FixedTextes
+ if (GetSlotId() != SID_FM_RECORD_TOTAL)
+ return;
+
+ XubString aText;
+ if (pState)
+ aText = ((SfxStringItem*)pState)->GetValue();
+ else
+ aText = '?';
+
+ pFixedText->SetText( aText );
+ pFixedText->Update();
+ pFixedText->Flush();
+
+ SfxToolBoxControl::StateChanged( nSID, eState,pState );
+}
+
+//========================================================================
+// SvxFmTbxNextRec
+//========================================================================
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxNextRec, SfxBoolItem );
+
+//-----------------------------------------------------------------------
+SvxFmTbxNextRec::SvxFmTbxNextRec( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ rTbx.SetItemBits(nId, rTbx.GetItemBits(nId) | TIB_REPEAT);
+
+ AllSettings aSettings = rTbx.GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+ aMouseSettings.SetButtonRepeat(aMouseSettings.GetButtonRepeat() / 4);
+ aSettings.SetMouseSettings(aMouseSettings);
+ rTbx.SetSettings(aSettings, TRUE);
+}
+
+//========================================================================
+// SvxFmTbxPrevRec
+//========================================================================
+SFX_IMPL_TOOLBOX_CONTROL( SvxFmTbxPrevRec, SfxBoolItem );
+
+//-----------------------------------------------------------------------
+SvxFmTbxPrevRec::SvxFmTbxPrevRec( USHORT nSlotId, USHORT nId, ToolBox& rTbx )
+ :SfxToolBoxControl( nSlotId, nId, rTbx )
+{
+ rTbx.SetItemBits(nId, rTbx.GetItemBits(nId) | TIB_REPEAT);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/typeconversionclient.cxx b/svx/source/form/typeconversionclient.cxx
new file mode 100644
index 000000000000..fd9427c1aa1a
--- /dev/null
+++ b/svx/source/form/typeconversionclient.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include "typeconversionclient.hxx"
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+ //====================================================================
+ //= OTypeConversionClient
+ //====================================================================
+ //--------------------------------------------------------------------
+ OTypeConversionClient::OTypeConversionClient()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool OTypeConversionClient::ensureLoaded() const
+ {
+ if ( !ODbtoolsClient::ensureLoaded() )
+ return false;
+ m_xTypeConversion = getFactory()->getTypeConversionHelper();
+ return m_xTypeConversion.is();
+ }
+
+//........................................................................
+} // namespace svxform
+//........................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/typemap.cxx b/svx/source/form/typemap.cxx
new file mode 100644
index 000000000000..d0f9763d770f
--- /dev/null
+++ b/svx/source/form/typemap.cxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <sfx2/objitem.hxx>
+#include <sfx2/msg.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/postitem.hxx>
+#include "clipfmtitem.hxx"
+#include <editeng/fhgtitem.hxx>
+#include "editeng/fontitem.hxx"
+#include <editeng/charreliefitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/emphitem.hxx>
+
+#include <editeng/memberids.hrc>
+#define SFX_TYPEMAP
+#include "svxslots.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/form/xfm_addcondition.cxx b/svx/source/form/xfm_addcondition.cxx
new file mode 100644
index 000000000000..aff2199bd49d
--- /dev/null
+++ b/svx/source/form/xfm_addcondition.cxx
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "xfm_addcondition.hxx"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+#include <cppuhelper/typeprovider.hxx>
+#include "datanavi.hxx"
+#include <vcl/msgbox.hxx>
+
+//........................................................................
+namespace svxform
+{
+//........................................................................
+
+#define PROPERTY_ID_BINDING 5724
+#define PROPERTY_ID_FORM_MODEL 5725
+#define PROPERTY_ID_FACET_NAME 5726
+#define PROPERTY_ID_CONDITION_VALUE 5727
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::xforms;
+
+ //====================================================================
+ //= OAddConditionDialog
+ //====================================================================
+ //--------------------------------------------------------------------
+ Reference< XInterface > SAL_CALL OAddConditionDialog_Create( const Reference< XMultiServiceFactory > & _rxORB )
+ {
+ return OAddConditionDialog::Create( _rxORB );
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< ::rtl::OUString > SAL_CALL OAddConditionDialog_GetSupportedServiceNames()
+ {
+ ::comphelper::StringSequence aSupported( 1 );
+ aSupported.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xforms.ui.dialogs.AddCondition" ) );
+ return aSupported;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString SAL_CALL OAddConditionDialog_GetImplementationName()
+ {
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.svx.OAddConditionDialog"));
+ }
+
+ //====================================================================
+ //= OAddConditionDialog
+ //====================================================================
+ //--------------------------------------------------------------------
+ OAddConditionDialog::OAddConditionDialog( const Reference< XMultiServiceFactory >& _rxORB )
+ :OAddConditionDialogBase( _rxORB )
+ {
+ registerProperty(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Binding" ) ),
+ PROPERTY_ID_BINDING,
+ PropertyAttribute::TRANSIENT,
+ &m_xBinding,
+ ::getCppuType( &m_xBinding )
+ );
+
+ registerProperty(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FacetName" ) ),
+ PROPERTY_ID_FACET_NAME,
+ PropertyAttribute::TRANSIENT,
+ &m_sFacetName,
+ ::getCppuType( &m_sFacetName )
+ );
+
+ registerProperty(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ConditionValue" ) ),
+ PROPERTY_ID_CONDITION_VALUE,
+ PropertyAttribute::TRANSIENT,
+ &m_sConditionValue,
+ ::getCppuType( &m_sConditionValue )
+ );
+
+ registerProperty(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FormModel" ) ),
+ PROPERTY_ID_FORM_MODEL,
+ PropertyAttribute::TRANSIENT,
+ &m_xWorkModel,
+ ::getCppuType( &m_xWorkModel )
+ );
+ }
+
+ //-------------------------------------------------------------------------
+ Sequence<sal_Int8> SAL_CALL OAddConditionDialog::getImplementationId( ) throw(RuntimeException)
+ {
+ static ::cppu::OImplementationId * pId = 0;
+ if (! pId)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if (! pId)
+ {
+ static ::cppu::OImplementationId aId;
+ pId = &aId;
+ }
+ }
+ return pId->getImplementationId();
+ }
+
+ //-------------------------------------------------------------------------
+ Reference< XInterface > SAL_CALL OAddConditionDialog::Create( const Reference< XMultiServiceFactory >& _rxFactory )
+ {
+ return *( new OAddConditionDialog( _rxFactory ) );
+ }
+
+ //-------------------------------------------------------------------------
+ ::rtl::OUString SAL_CALL OAddConditionDialog::getImplementationName() throw(RuntimeException)
+ {
+ return OAddConditionDialog_GetImplementationName();
+ }
+
+ //-------------------------------------------------------------------------
+ Sequence< ::rtl::OUString > SAL_CALL OAddConditionDialog::getSupportedServiceNames() throw(RuntimeException)
+ {
+ return OAddConditionDialog_GetSupportedServiceNames();
+ }
+
+ //-------------------------------------------------------------------------
+ Reference<XPropertySetInfo> SAL_CALL OAddConditionDialog::getPropertySetInfo() throw(RuntimeException)
+ {
+ return createPropertySetInfo( getInfoHelper() );
+ }
+
+ //-------------------------------------------------------------------------
+ ::cppu::IPropertyArrayHelper& OAddConditionDialog::getInfoHelper()
+ {
+ return *const_cast< OAddConditionDialog* >( this )->getArrayHelper();
+ }
+
+ //------------------------------------------------------------------------------
+ ::cppu::IPropertyArrayHelper* OAddConditionDialog::createArrayHelper( ) const
+ {
+ Sequence< Property > aProperties;
+ describeProperties( aProperties );
+ return new ::cppu::OPropertyArrayHelper( aProperties );
+ }
+
+ //------------------------------------------------------------------------------
+ Dialog* OAddConditionDialog::createDialog(Window* _pParent)
+ {
+ if ( !m_xBinding.is() || !m_sFacetName.getLength() )
+ throw RuntimeException( ::rtl::OUString(), *this );
+
+ return new AddConditionDialog( _pParent, m_sFacetName, m_xBinding );
+ }
+
+ //------------------------------------------------------------------------------
+ void OAddConditionDialog::executedDialog( sal_Int16 _nExecutionResult )
+ {
+ OAddConditionDialogBase::executedDialog( _nExecutionResult );
+ if ( _nExecutionResult == RET_OK )
+ m_sConditionValue = static_cast< AddConditionDialog* >( m_pDialog )->GetCondition();
+ }
+
+//........................................................................
+} // namespace svxformv
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */