/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_toolkit.hxx"
#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/WindowAttribute.hpp>
#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#ifndef _COM_SUN_STAR_LAN_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/resource/XStringResourceResolver.hpp>
#include <toolkit/controls/unocontrol.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <rtl/memory.h>
#include <rtl/uuid.h>
#include <vos/mutex.hxx>
#include <tools/string.hxx>
#include <tools/table.hxx>
#include <tools/date.hxx>
#include <tools/time.hxx>
#include <tools/urlobj.hxx>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
#include <comphelper/stl_types.hxx>
#include <comphelper/processfactory.hxx>
#include <toolkit/helper/property.hxx>
#include <toolkit/helper/servicenames.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/awt/vclxwindow.hxx>
#include <vcl/svapp.hxx>
#include <vos/mutex.hxx>
#include <toolkit/controls/accessiblecontrolcontext.hxx>
#include <comphelper/container.hxx>

#include <algorithm>
#include <set>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;

using ::com::sun::star::accessibility::XAccessibleContext;
using ::com::sun::star::accessibility::XAccessible;

struct LanguageDependentProp
{
	const char* pPropName;
	sal_Int32   nPropNameLength;
};

static const LanguageDependentProp aLanguageDependentProp[] =
{
	{ "Text",            4 },
	{ "Label",           5 },
	{ "Title",           5 },
	{ "HelpText",        8 },
	{ "CurrencySymbol", 14 },
	{ "StringItemList", 14 },
	{ 0, 0                 }
};

static Sequence< ::rtl::OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
{
	Sequence< ::rtl::OUString> aNames;
	Reference< XPropertySetInfo >  xPSInf = rxModel->getPropertySetInfo();
	DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
	if ( xPSInf.is() )
	{
		Sequence< Property> aProps = xPSInf->getProperties();
		sal_Int32 nLen = aProps.getLength();
		aNames = Sequence< ::rtl::OUString>( nLen );
		::rtl::OUString* pNames = aNames.getArray();
		const Property* pProps = aProps.getConstArray();
		for ( sal_Int32 n = 0; n < nLen; ++n, ++pProps, ++pNames)
			*pNames = pProps->Name;
	}
	return aNames;
}

//	====================================================
class VclListenerLock
{
private:
	VCLXWindow*  m_pLockWindow;

public:
	inline VclListenerLock( VCLXWindow* _pLockWindow )
		:m_pLockWindow( _pLockWindow )
	{
		if ( m_pLockWindow )
			m_pLockWindow->suspendVclEventListening( );
	}
	inline ~VclListenerLock( )
	{
		if ( m_pLockWindow )
			m_pLockWindow->resumeVclEventListening( );
	}

private:
	VclListenerLock();                                      // never implemented
	VclListenerLock( const VclListenerLock& );              // never implemented
	VclListenerLock& operator=( const VclListenerLock& );   // never implemented
};

typedef ::std::map< ::rtl::OUString, sal_Int32 >    MapString2Int;
struct UnoControl_Data
{
	MapString2Int   aSuspendedPropertyNotifications;
	// true if and only if our model has a property ResourceResolver
	bool            bLocalizationSupport;

	UnoControl_Data()
		:aSuspendedPropertyNotifications()
		,bLocalizationSupport( false )
	{
	}
};

//	----------------------------------------------------
//	class UnoControl
//	----------------------------------------------------
DBG_NAME( UnoControl )
UnoControl::UnoControl()
	:maContext( ::comphelper::getProcessServiceFactory() )
	,maDisposeListeners( *this )
	,maWindowListeners( *this )
	,maFocusListeners( *this )
	,maKeyListeners( *this )
	,maMouseListeners( *this )
	,maMouseMotionListeners( *this )
	,maPaintListeners( *this )
	,maModeChangeListeners( GetMutex() )
	,mpData( new UnoControl_Data )
{
	DBG_CTOR( UnoControl, NULL );
	OSL_ENSURE( false, "UnoControl::UnoControl: not implemented. Well, not really." );
	// just implemented to let the various FooImplInheritanceHelper compile, you should use the
	// version taking a service factory
}

UnoControl::UnoControl( const Reference< XMultiServiceFactory >& i_factory )
	: maContext( i_factory )
	, maDisposeListeners( *this )
	, maWindowListeners( *this )
	, maFocusListeners( *this )
	, maKeyListeners( *this )
	, maMouseListeners( *this )
	, maMouseMotionListeners( *this )
	, maPaintListeners( *this )
	, maModeChangeListeners( GetMutex() )
	, mpData( new UnoControl_Data )
{
	DBG_CTOR( UnoControl, NULL );
	mbDisposePeer = sal_True;
	mbRefeshingPeer = sal_False;
	mbCreatingPeer = sal_False;
	mbCreatingCompatiblePeer = sal_False;
	mbDesignMode = sal_False;
}

UnoControl::~UnoControl()
{
	DELETEZ( mpData );
	DBG_DTOR( UnoControl, NULL );
}

::rtl::OUString UnoControl::GetComponentServiceName()
{
	return ::rtl::OUString();
}

Reference< XWindowPeer >	UnoControl::ImplGetCompatiblePeer( sal_Bool bAcceptExistingPeer )
{
	DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - rekursive?" );

	mbCreatingCompatiblePeer = sal_True;

	Reference< XWindowPeer > xCompatiblePeer;

	if ( bAcceptExistingPeer )
		xCompatiblePeer = getPeer();

	if ( !xCompatiblePeer.is() )
	{
		// Peer unsichtbar erzeugen...
		sal_Bool bVis = maComponentInfos.bVisible;
		if( bVis )
			maComponentInfos.bVisible = sal_False;

		Reference< XWindowPeer >	xCurrentPeer = getPeer();
		setPeer( NULL );

		// queryInterface ourself, to allow aggregation
		Reference< XControl > xMe;
		OWeakAggObject::queryInterface( ::getCppuType( &xMe ) ) >>= xMe;

		Window* pParentWindow( NULL );
		{
			osl::Guard< vos::IMutex > aGuard( Application::GetSolarMutex() );
			pParentWindow = dynamic_cast< Window* >( Application::GetDefaultDevice() );
			ENSURE_OR_THROW( pParentWindow != NULL, "could obtain a default parent window!" );
		}
		try
		{
			xMe->createPeer( NULL, pParentWindow->GetComponentInterface( sal_True ) );
		}
		catch( const Exception& )
		{
			mbCreatingCompatiblePeer = sal_False;
			throw;
		}
		xCompatiblePeer = getPeer();
		setPeer( xCurrentPeer );

		if ( xCompatiblePeer.is() && mxGraphics.is() )
		{
			Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
			if ( xPeerView.is() )
				xPeerView->setGraphics( mxGraphics );
		}

		if( bVis )
			maComponentInfos.bVisible = sal_True;
	}

	mbCreatingCompatiblePeer = sal_False;

	return xCompatiblePeer;
}

bool UnoControl::ImplCheckLocalize( ::rtl::OUString& _rPossiblyLocalizable )
{
	if  (   !mpData->bLocalizationSupport
		||  ( _rPossiblyLocalizable.getLength() == 0 )
		||  ( _rPossiblyLocalizable[0] != '&' )
			// TODO: make this reasonable. At the moment, everything which by accident starts with a & is considered
			// localizable, which is probably wrong.
		)
		return false;

	try
	{
		Reference< XPropertySet > xPropSet( mxModel, UNO_QUERY_THROW );
		Reference< resource::XStringResourceResolver > xStringResourceResolver(
			xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceResolver" ) ) ),
			UNO_QUERY
		);
		if ( xStringResourceResolver.is() )
		{
			::rtl::OUString aLocalizationKey( _rPossiblyLocalizable.copy( 1 ) );
			_rPossiblyLocalizable = xStringResourceResolver->resolveString( aLocalizationKey );
			return true;
		}
	}
	catch( const Exception& )
	{
		DBG_UNHANDLED_EXCEPTION();
	}
	return false;
}

void UnoControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
{
	// since a change made in propertiesChange, we can't be sure that this is called with an valid getPeer(),
	// this assumption may be false in some (seldom) multi-threading scenarios (cause propertiesChange
	// releases our mutex before calling here in)
	// That's why this additional check

	if ( mxVclWindowPeer.is() )
	{
		Any aConvertedValue( rVal );

		if ( mpData->bLocalizationSupport )
		{
			// We now support a mapping for language dependent properties. This is the
			// central method to implement it.
			if (( rPropName.equalsAsciiL( "Text",            4 )) ||
				( rPropName.equalsAsciiL( "Label",           5 )) ||
				( rPropName.equalsAsciiL( "Title",           5 )) ||
				( rPropName.equalsAsciiL( "HelpText",        8 )) ||
				( rPropName.equalsAsciiL( "CurrencySymbol", 14 )) ||
				( rPropName.equalsAsciiL( "StringItemList", 14 )) )
			{
				::rtl::OUString aValue;
				uno::Sequence< rtl::OUString > aSeqValue;
				if ( aConvertedValue >>= aValue )
				{
					if ( ImplCheckLocalize( aValue ) )
						aConvertedValue <<= aValue;
				}
				else if ( aConvertedValue >>= aSeqValue )
				{
					for ( sal_Int32 i = 0; i < aSeqValue.getLength(); i++ )
						ImplCheckLocalize( aSeqValue[i] );
					aConvertedValue <<= aSeqValue;
				}
			}
		}

		mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
	}
}

void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
{
}

Reference< XWindow >	UnoControl::getParentPeer() const
{
	Reference< XWindow > xPeer;
	if( mxContext.is() )
	{
		Reference< XControl > xContComp( mxContext, UNO_QUERY );
		if ( xContComp.is() )
		{
			Reference< XWindowPeer > xP = xContComp->getPeer();
			if ( xP.is() )
				xP->queryInterface( ::getCppuType((const Reference< XWindow >*)0) ) >>= xPeer;
		}
	}
	return xPeer;
}

void UnoControl::updateFromModel()
{
	// Alle standard Properties werden ausgelesen und in das Peer übertragen
	if( getPeer().is() )
	{
		Reference< XMultiPropertySet >	xPropSet( mxModel, UNO_QUERY );
		if( xPropSet.is() )
		{
			Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
			xPropSet->firePropertiesChangeEvent( aNames, this );
		}
	}
}


// XTypeProvider
IMPL_IMPLEMENTATION_ID( UnoControl )

void UnoControl::disposeAccessibleContext()
{
	Reference< XComponent > xContextComp( maAccessibleContext.get(), UNO_QUERY );
	if ( xContextComp.is() )
	{
		maAccessibleContext = NULL;
		try
		{
			xContextComp->removeEventListener( this );
			xContextComp->dispose();
		}
		catch( const Exception& )
		{
			DBG_ERROR( "UnoControl::disposeAccessibleContext: could not dispose my AccessibleContext!" );
		}
	}
}

void UnoControl::dispose(  ) throw(RuntimeException)
{
	Reference< XWindowPeer > xPeer;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if( mbDisposePeer )
		{
			xPeer = mxPeer;
		}
		setPeer( NULL );
	}
	if( xPeer.is() )
	{
		xPeer->dispose();
	}

	// dispose and release our AccessibleContext
	disposeAccessibleContext();

	EventObject aDisposeEvent;
	aDisposeEvent.Source = static_cast< XAggregation* >( this );

	maDisposeListeners.disposeAndClear( aDisposeEvent );
	maWindowListeners.disposeAndClear( aDisposeEvent );
	maFocusListeners.disposeAndClear( aDisposeEvent );
	maKeyListeners.disposeAndClear( aDisposeEvent );
	maMouseListeners.disposeAndClear( aDisposeEvent );
	maMouseMotionListeners.disposeAndClear( aDisposeEvent );
	maPaintListeners.disposeAndClear( aDisposeEvent );
	maModeChangeListeners.disposeAndClear( aDisposeEvent );

	// Model wieder freigeben
	setModel( Reference< XControlModel > () );
	setContext( Reference< XInterface > () );
}

void UnoControl::addEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	maDisposeListeners.addInterface( rxListener );
}

void UnoControl::removeEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	maDisposeListeners.removeInterface( rxListener );
}

sal_Bool UnoControl::requiresNewPeer( const ::rtl::OUString& /* _rPropertyName */ ) const
{
	return sal_False;
}

// XPropertiesChangeListener
void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
{
	Sequence< PropertyChangeEvent > aEvents( rEvents );
	{
		::osl::MutexGuard aGuard( GetMutex() );

		if ( !mpData->aSuspendedPropertyNotifications.empty() )
		{
			// strip the property which we are currently updating (somewhere up the stack)
			PropertyChangeEvent* pEvents = aEvents.getArray();
			PropertyChangeEvent* pEventsEnd = pEvents + aEvents.getLength();
			for ( ; pEvents < pEventsEnd; )
				if ( mpData->aSuspendedPropertyNotifications.find( pEvents->PropertyName ) != mpData->aSuspendedPropertyNotifications.end() )
				{
					if ( pEvents != pEventsEnd )
						::std::copy( pEvents + 1, pEventsEnd, pEvents );
					--pEventsEnd;
				}
				else
					++pEvents;
			aEvents.realloc( pEventsEnd - aEvents.getConstArray() );

			if ( !aEvents.getLength() )
				return;
		}
	}

	ImplModelPropertiesChanged( aEvents );
}

void UnoControl::ImplLockPropertyChangeNotification( const ::rtl::OUString& rPropertyName, bool bLock )
{
	MapString2Int::iterator pos = mpData->aSuspendedPropertyNotifications.find( rPropertyName );
	if ( bLock )
	{
		if ( pos == mpData->aSuspendedPropertyNotifications.end() )
			pos = mpData->aSuspendedPropertyNotifications.insert( MapString2Int::value_type( rPropertyName, 0 ) ).first;
		++pos->second;
	}
	else
	{
		OSL_ENSURE( pos != mpData->aSuspendedPropertyNotifications.end(), "UnoControl::ImplLockPropertyChangeNotification: property not locked!" );
		if ( pos != mpData->aSuspendedPropertyNotifications.end() )
		{
			OSL_ENSURE( pos->second > 0, "UnoControl::ImplLockPropertyChangeNotification: invalid suspension counter!" );
			if ( 0 == --pos->second )
				mpData->aSuspendedPropertyNotifications.erase( pos );
		}
	}
}

void UnoControl::ImplLockPropertyChangeNotifications( const Sequence< ::rtl::OUString >& rPropertyNames, bool bLock )
{
	for (   const ::rtl::OUString* pPropertyName = rPropertyNames.getConstArray();
			pPropertyName != rPropertyNames.getConstArray() + rPropertyNames.getLength();
			++pPropertyName
		)
		ImplLockPropertyChangeNotification( *pPropertyName, bLock );
}

void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
{
	::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );

	if( getPeer().is() )
	{
		DECLARE_STL_VECTOR( PropertyValue, PropertyValueVector);
		PropertyValueVector 	aPeerPropertiesToSet;
		sal_Int32				nIndependentPos = 0;
		bool                    bResourceResolverSet( false );
			// position where to insert the independent properties into aPeerPropertiesToSet,
			// dependent ones are inserted at the end of the vector

		sal_Bool bNeedNewPeer = sal_False;
			// some properties require a re-creation of the peer, 'cause they can't be changed on the fly

		Reference< XControlModel > xOwnModel( getModel(), UNO_QUERY );
			// our own model for comparison
		Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
		Reference< XPropertySetInfo > xPSI( xPS->getPropertySetInfo(), UNO_QUERY );
		OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );

		const PropertyChangeEvent* pEvents = rEvents.getConstArray();

		sal_Int32 nLen = rEvents.getLength();
		aPeerPropertiesToSet.reserve(nLen);

		for( sal_Int32 i = 0; i < nLen; ++i, ++pEvents )
		{
			Reference< XControlModel > xModel( pEvents->Source, UNO_QUERY );
			sal_Bool bOwnModel = xModel.get() == xOwnModel.get();
			if ( !bOwnModel )
				continue;

			// Detect changes on our resource resolver which invalidates
			// automatically some language dependent properties.
			if ( pEvents->PropertyName.equalsAsciiL( "ResourceResolver", 16 ))
			{
				Reference< resource::XStringResourceResolver > xStrResolver;
				if ( pEvents->NewValue >>= xStrResolver )
					bResourceResolverSet = xStrResolver.is();
			}

			sal_uInt16 nPType = GetPropertyId( pEvents->PropertyName );
			if ( mbDesignMode && mbDisposePeer && !mbRefeshingPeer && !mbCreatingPeer )
			{
				// if we're in design mode, then some properties can change which
				// require creating a *new* peer (since these properties cannot
				// be switched at existing peers)
				if ( nPType )
					bNeedNewPeer = ( nPType == BASEPROPERTY_BORDER )
								|| ( nPType == BASEPROPERTY_MULTILINE )
								|| ( nPType == BASEPROPERTY_DROPDOWN )
								|| ( nPType == BASEPROPERTY_HSCROLL )
								|| ( nPType == BASEPROPERTY_VSCROLL )
								|| ( nPType == BASEPROPERTY_AUTOHSCROLL )
								|| ( nPType == BASEPROPERTY_AUTOVSCROLL )
								|| ( nPType == BASEPROPERTY_ORIENTATION )
								|| ( nPType == BASEPROPERTY_SPIN )
								|| ( nPType == BASEPROPERTY_ALIGN )
								|| ( nPType == BASEPROPERTY_PAINTTRANSPARENT );
				else
					bNeedNewPeer = requiresNewPeer( pEvents->PropertyName );

				if ( bNeedNewPeer )
					break;
			}

			if ( nPType && ( nLen > 1 ) && DoesDependOnOthers( nPType ) )
			{
				// Properties die von anderen abhängen erst hinterher einstellen,
				// weil sie von anderen Properties abhängig sind, die aber erst später
				// eingestellt werden, z.B. VALUE nach VALUEMIN/MAX.
				aPeerPropertiesToSet.push_back(PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
			}
			else
			{
				if ( bResourceResolverSet )
				{
					// The resource resolver property change should be one of the first ones.
					// All language dependent properties are dependent on this property.
					// As BASEPROPERTY_NATIVE_WIDGET_LOOK is not dependent on resource
					// resolver. We don't need to handle a special order for these two props.
					aPeerPropertiesToSet.insert(
						aPeerPropertiesToSet.begin(),
						PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
					++nIndependentPos;
				}
				else if ( nPType == BASEPROPERTY_NATIVE_WIDGET_LOOK )
				{
					// since *a lot* of other properties might be overruled by this one, we need
					// a special handling:
					// NativeWidgetLook needs to be set first: If it is set to ON, all other
					// properties describing the look (e.g. BackgroundColor) are ignored, anyway.
					// If it is switched OFF, then we need to do it first because else it will
					// overrule other look-related properties, and re-initialize them from system
					// defaults.
					aPeerPropertiesToSet.insert(
						aPeerPropertiesToSet.begin(),
						PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
					++nIndependentPos;
				}
				else
				{
					aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
						PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
					++nIndependentPos;
				}
			}
		}

		Reference< XWindow >	xParent = getParentPeer();
		Reference< XControl > xThis( (XAggregation*)(::cppu::OWeakAggObject*)this, UNO_QUERY );
		// call createPeer via a interface got from queryInterface, so the aggregating class can intercept it

		DBG_ASSERT( !bNeedNewPeer || xParent.is(), "Need new peer, but don't have a parent!" );

		// Check if we have to update language dependent properties
		if ( !bNeedNewPeer && bResourceResolverSet )
		{
			// Add language dependent properties into the peer property set.
			// Our resource resolver has been changed and we must be sure
			// that language dependent props use the new resolver.
			const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
			while ( pLangDepProp->pPropName != 0 )
			{
				bool bMustBeInserted( true );
				for ( sal_uInt32 i = 0; i < aPeerPropertiesToSet.size(); i++ )
				{
					if ( aPeerPropertiesToSet[i].Name.equalsAsciiL(
							pLangDepProp->pPropName, pLangDepProp->nPropNameLength ))
					{
						bMustBeInserted = false;
						break;
					}
				}

				if ( bMustBeInserted )
				{
					// Add language dependent props at the end
					::rtl::OUString aPropName( ::rtl::OUString::createFromAscii( pLangDepProp->pPropName ));
					if ( xPSI.is() && xPSI->hasPropertyByName( aPropName ) )
					{
						aPeerPropertiesToSet.push_back(
							PropertyValue( aPropName, 0, xPS->getPropertyValue( aPropName ), PropertyState_DIRECT_VALUE ) );
					}
				}

				++pLangDepProp;
			}
		}
		aGuard.clear();

		// clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
		// #82300# - 2000-12-21 - fs@openoffice.org
		if (bNeedNewPeer && xParent.is())
		{
			vos::OGuard aVclGuard( Application::GetSolarMutex() );
				// and now this is the final withdrawal:
				// With 83561, I have no other idea than locking the SolarMutex here ....
				// I really hate the fact that VCL is not threadsafe ....
				// #83561# - 2001-03-01 - fs@openoffice.org

			// Funktioniert beim Container nicht!
			getPeer()->dispose();
			mxPeer.clear();
			mxVclWindowPeer = NULL;
			mbRefeshingPeer = sal_True;
			Reference< XWindowPeer >	xP( xParent, UNO_QUERY );
			xThis->createPeer( Reference< XToolkit > (), xP );
			mbRefeshingPeer = sal_False;
			aPeerPropertiesToSet.clear();
		}

		// lock the multiplexing of VCL events to our UNO listeners
		// this is for compatibility reasons: in OOo 1.0.x, changes which were done at the
		// model did not cause the listeners of the controls/peers to be called
		// Since the implementations for the listeners changed a lot towards 1.1, this
		// would not be the case anymore, if we would not do this listener-lock below
		// #i14703# - 2003-05-23 - fs@openoffice.org
		Window* pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
		VCLXWindow* pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : NULL;
		VclListenerLock aNoVclEventMultiplexing( pPeer );

		// setting peer properties may result in an attempt to acquire the solar mutex, 'cause the peers
		// usually don't have an own mutex but use the SolarMutex instead.
		// To prevent deadlocks resulting from this, we do this without our own mutex locked
		// 2000-11-03 - fs@openoffice.org
		PropertyValueVectorIterator aEnd = aPeerPropertiesToSet.end();
		for (	PropertyValueVectorIterator aLoop = aPeerPropertiesToSet.begin();
				aLoop != aEnd;
				++aLoop
			)
		{
			ImplSetPeerProperty( aLoop->Name, aLoop->Value );
		}
	}
}

void UnoControl::disposing( const EventObject& rEvt ) throw(RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
	// bei "Multible Inheritance" nicht unterschiedliche Typen vergleichen.

	if ( maAccessibleContext.get() == rEvt.Source )
	{
		// just in case the context is disposed, but not released - ensure that we do not re-use it in the future
		maAccessibleContext = NULL;
	}
	else if( mxModel.get() == Reference< XControlModel >(rEvt.Source,UNO_QUERY).get() )
	{
		// #62337# if the model dies, it does not make sense for us to live ...
		Reference< XControl >  xThis = this;

		aGuard.clear();
		xThis->dispose();

		DBG_ASSERT( !mxModel.is(), "UnoControl::disposing: invalid dispose behaviour!" );
		mxModel.clear();
	}
}


void SAL_CALL UnoControl::setOutputSize( const awt::Size& aSize ) throw (RuntimeException)
{
	Reference< XWindow2 > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerWindow = xPeerWindow.query( getPeer() );
	}

	if ( xPeerWindow.is() )
		xPeerWindow->setOutputSize( aSize );
}

namespace
{
	template < typename RETVALTYPE >
	RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), RETVALTYPE _aDefault )
	{
		RETVALTYPE aReturn( _aDefault );

		Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
		if ( xPeerWindow.is() )
			aReturn = (xPeerWindow.get()->*_pMethod)();

		return aReturn;
	}
}

awt::Size SAL_CALL UnoControl::getOutputSize(  ) throw (RuntimeException)
{
	return lcl_askPeer( getPeer(), &XWindow2::getOutputSize, awt::Size() );
}

::sal_Bool SAL_CALL UnoControl::isVisible(  ) throw (RuntimeException)
{
	return lcl_askPeer( getPeer(), &XWindow2::isVisible, maComponentInfos.bVisible );
}

::sal_Bool SAL_CALL UnoControl::isActive(  ) throw (RuntimeException)
{
	return lcl_askPeer( getPeer(), &XWindow2::isActive, sal_False );
}

::sal_Bool SAL_CALL UnoControl::isEnabled(  ) throw (RuntimeException)
{
	return lcl_askPeer( getPeer(), &XWindow2::isEnabled, maComponentInfos.bEnable );
}

::sal_Bool SAL_CALL UnoControl::hasFocus(  ) throw (RuntimeException)
{
	return lcl_askPeer( getPeer(), &XWindow2::hasFocus, sal_False );
}

// XWindow
void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) throw(RuntimeException)
{
	Reference< XWindow > xWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );

		if ( Flags & awt::PosSize::X )
			maComponentInfos.nX = X;
		if ( Flags & awt::PosSize::Y )
			maComponentInfos.nY = Y;
		if ( Flags & awt::PosSize::WIDTH )
			maComponentInfos.nWidth = Width;
		if ( Flags & awt::PosSize::HEIGHT )
			maComponentInfos.nHeight = Height;
		maComponentInfos.nFlags |= Flags;

		xWindow = xWindow.query( getPeer() );
	}

	if( xWindow.is() )
		xWindow->setPosSize( X, Y, Width, Height, Flags );
}

awt::Rectangle UnoControl::getPosSize(  ) throw(RuntimeException)
{
	awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
	Reference< XWindow > xWindow;

	{
		::osl::MutexGuard aGuard( GetMutex() );
		xWindow = xWindow.query( getPeer() );
	}

	if( xWindow.is() )
		aRect = xWindow->getPosSize();
	return aRect;
}

void UnoControl::setVisible( sal_Bool bVisible ) throw(RuntimeException)
{
	Reference< XWindow > xWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );

		// Visible status ist Sache der View
		maComponentInfos.bVisible = bVisible;
		xWindow = xWindow.query( getPeer() );
	}
	if ( xWindow.is() )
		xWindow->setVisible( bVisible );
}

void UnoControl::setEnable( sal_Bool bEnable ) throw(RuntimeException)
{
	Reference< XWindow > xWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );

		// Enable status ist Sache der View
		maComponentInfos.bEnable = bEnable;
		xWindow = xWindow.query( getPeer() );
	}
	if ( xWindow.is() )
		xWindow->setEnable( bEnable );
}

void UnoControl::setFocus(	) throw(RuntimeException)
{
	Reference< XWindow > xWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xWindow = xWindow.query( getPeer() );
	}
	if ( xWindow.is() )
		xWindow->setFocus();
}

void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maWindowListeners.addInterface( rxListener );
		if ( maWindowListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addWindowListener( &maWindowListeners );
}

void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maWindowListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maWindowListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removeWindowListener( &maWindowListeners );
}

void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maFocusListeners.addInterface( rxListener );
		if ( maFocusListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addFocusListener( &maFocusListeners );
}

void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maFocusListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maFocusListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removeFocusListener( &maFocusListeners );
}

void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maKeyListeners.addInterface( rxListener );
		if ( maKeyListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addKeyListener( &maKeyListeners);
}

void UnoControl::removeKeyListener( const Reference< XKeyListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maKeyListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maKeyListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removeKeyListener( &maKeyListeners);
}

void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maMouseListeners.addInterface( rxListener );
		if ( maMouseListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addMouseListener( &maMouseListeners);
}

void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maMouseListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maMouseListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removeMouseListener( &maMouseListeners );
}

void UnoControl::addMouseMotionListener( const Reference< XMouseMotionListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maMouseMotionListeners.addInterface( rxListener );
		if ( maMouseMotionListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addMouseMotionListener( &maMouseMotionListeners);
}

void UnoControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maMouseMotionListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maMouseMotionListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removeMouseMotionListener( &maMouseMotionListeners );
}

void UnoControl::addPaintListener( const Reference< XPaintListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		maPaintListeners.addInterface( rxListener );
		if ( maPaintListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->addPaintListener( &maPaintListeners);
}

void UnoControl::removePaintListener( const Reference< XPaintListener >& rxListener ) throw(RuntimeException)
{
	Reference< XWindow > xPeerWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( maPaintListeners.getLength() == 1 )
			xPeerWindow = xPeerWindow.query( getPeer() );
		maPaintListeners.removeInterface( rxListener );
	}
	if ( xPeerWindow.is() )
		xPeerWindow->removePaintListener( &maPaintListeners );
}

// XView
sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice ) throw(RuntimeException)
{
	Reference< XView > xView;
	{
		::osl::MutexGuard aGuard( GetMutex() );

		mxGraphics = rDevice;
		xView = xView.query( getPeer() );
	}
	return xView.is() ? xView->setGraphics( rDevice ) : sal_True;
}

Reference< XGraphics > UnoControl::getGraphics(  ) throw(RuntimeException)
{
	return mxGraphics;
}

awt::Size UnoControl::getSize(  ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
	return awt::Size( maComponentInfos.nWidth, maComponentInfos.nHeight );
}

void UnoControl::draw( sal_Int32 x, sal_Int32 y ) throw(RuntimeException)
{
	Reference< XWindowPeer > xDrawPeer;
	Reference< XView > xDrawPeerView;

	bool bDisposeDrawPeer( false );
	{
		::osl::MutexGuard aGuard( GetMutex() );

		xDrawPeer = ImplGetCompatiblePeer( sal_True );
		bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );

		xDrawPeerView.set( xDrawPeer, UNO_QUERY );
		DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
	}

	if ( xDrawPeerView.is() )
	{
		Reference< XVclWindowPeer > xWindowPeer;
		xWindowPeer.set( xDrawPeer, UNO_QUERY );
		if ( xWindowPeer.is() )
			xWindowPeer->setDesignMode( mbDesignMode );
		xDrawPeerView->draw( x, y );
	}

	if ( bDisposeDrawPeer )
		xDrawPeer->dispose();
}

void UnoControl::setZoom( float fZoomX, float fZoomY ) throw(RuntimeException)
{
	Reference< XView > xView;
	{
		::osl::MutexGuard aGuard( GetMutex() );

		maComponentInfos.nZoomX = fZoomX;
		maComponentInfos.nZoomY = fZoomY;

		xView = xView.query( getPeer() );
	}
	if ( xView.is() )
		xView->setZoom( fZoomX, fZoomY );
}

// XControl
void UnoControl::setContext( const Reference< XInterface >& rxContext ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	mxContext = rxContext;
}

Reference< XInterface > UnoControl::getContext(  ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	return mxContext;
}

void UnoControl::peerCreated()
{
	Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
	if ( !xWindow.is() )
		return;

	if ( maWindowListeners.getLength() )
		xWindow->addWindowListener( &maWindowListeners );

	if ( maFocusListeners.getLength() )
		xWindow->addFocusListener( &maFocusListeners );

	if ( maKeyListeners.getLength() )
		xWindow->addKeyListener( &maKeyListeners );

	if ( maMouseListeners.getLength() )
		xWindow->addMouseListener( &maMouseListeners );

	if ( maMouseMotionListeners.getLength() )
		xWindow->addMouseMotionListener( &maMouseMotionListeners );

	if ( maPaintListeners.getLength() )
		xWindow->addPaintListener( &maPaintListeners );
}

void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer ) throw(RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );

	if ( !mxModel.is() )
	{
		RuntimeException aException;
		aException.Message = ::rtl::OUString::createFromAscii( "createPeer: no model!" );
		aException.Context = (XAggregation*)(::cppu::OWeakAggObject*)this;
		throw( aException );
	}

	if( !getPeer().is() )
	{
		mbCreatingPeer = sal_True;

		WindowClass eType;
		Reference< XToolkit >  xToolkit = rxToolkit;
		if( rParentPeer.is() && mxContext.is() )
		{
			// kein TopWindow
			if ( !xToolkit.is() )
				xToolkit = rParentPeer->getToolkit();
			Any aAny = OWeakAggObject::queryInterface( ::getCppuType((const Reference< XControlContainer>*)0) );
			Reference< XControlContainer > xC;
			aAny >>= xC;
			if( xC.is() )
				// Es ist ein Container
				eType = WindowClass_CONTAINER;
			else
				eType = WindowClass_SIMPLE;
		}
		else
		{ // Nur richtig, wenn es sich um ein Top Window handelt
			if( rParentPeer.is() )
			{
				if ( !xToolkit.is() )
					xToolkit = rParentPeer->getToolkit();
				eType = WindowClass_CONTAINER;
			}
			else
			{
				if ( !xToolkit.is() )
					xToolkit = VCLUnoHelper::CreateToolkit();
				eType = WindowClass_TOP;
			}
		}
		WindowDescriptor aDescr;
		aDescr.Type = eType;
		aDescr.WindowServiceName = GetComponentServiceName();
		aDescr.Parent = rParentPeer;
		aDescr.Bounds = getPosSize();
		aDescr.WindowAttributes = 0;

		// Border
		Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
		Reference< XPropertySetInfo >  xInfo = xPSet->getPropertySetInfo();

		Any aVal;
		::rtl::OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Int16 n = sal_Int16();
			if ( aVal >>= n )
			{
				if ( n )
					aDescr.WindowAttributes |= WindowAttribute::BORDER;
				else
					aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
			}
		}

		// DESKTOP_AS_PARENT
		if ( aDescr.Type == WindowClass_TOP )
		{
			aPropName = GetPropertyName( BASEPROPERTY_DESKTOP_AS_PARENT );
			if ( xInfo->hasPropertyByName( aPropName ) )
			{
				aVal = xPSet->getPropertyValue( aPropName );
				sal_Bool b = sal_Bool();
				if ( ( aVal >>= b ) && b)
					aDescr.ParentIndex = -1;
			}
		}
		// Moveable
		aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= WindowAttribute::MOVEABLE;
		}

		// Closeable
		aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= WindowAttribute::CLOSEABLE;
		}

		// Dropdown
		aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
		}

		// Spin
		aPropName = GetPropertyName( BASEPROPERTY_SPIN );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::SPIN;
		}

		// HScroll
		aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
		}

		// VScroll
		aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
		}

		// AutoHScroll
		aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOHSCROLL;
		}

		// AutoVScroll
		aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>= b ) && b)
				aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOVSCROLL;
		}

		// added for issue79712
		// NoLabel
		aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Bool b = sal_Bool();
			if ( ( aVal >>=b ) && b )
				aDescr.WindowAttributes |= VclWindowPeerAttribute::NOLABEL;
		}
		//issue79712 ends

		// Align
		aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
		if ( xInfo->hasPropertyByName( aPropName ) )
		{
			aVal = xPSet->getPropertyValue( aPropName );
			sal_Int16 n = sal_Int16();
			if ( aVal >>= n )
			{
				if ( n == PROPERTY_ALIGN_LEFT )
					aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
				else if ( n == PROPERTY_ALIGN_CENTER )
					aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
				else
					aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
			}
		}

		// Ableitungen die Möglichkeit geben die Attribute zu manipulieren
		PrepareWindowDescriptor(aDescr);

		// create the peer
		setPeer( xToolkit->createWindow( aDescr ) );

		// release the mutex guard (and work with copies of our members)
		// this is necessary as our peer may lock the SolarMutex (actually, all currently known peers do), so calling
		// into the peer with our own mutex locked may cause deadlocks
		// (We _really_ need peers which do not use the SolarMutex. It's really pissing me off that from time to
		// time deadlocks pop up because the low-level components like our peers use a mutex which usually
		// is locked at the top of the stack (it protects the global message looping). This is always dangerous, and
		// can not always be solved by tampering with other mutexes.
		// Unfortunately, the VCL used in the peers is not threadsafe, and by definition needs a locked SolarMutex.)
		// 82300 - 12/21/00 - FS
		UnoControlComponentInfos aComponentInfos(maComponentInfos);
		sal_Bool bDesignMode(mbDesignMode);

		Reference< XGraphics >  xGraphics( mxGraphics           );
		Reference< XView >      xView    ( getPeer(), UNO_QUERY );
		Reference< XWindow >    xWindow  ( getPeer(), UNO_QUERY );

		aGuard.clear();

		// the updateFromModel is done without a locked mutex, too.
		// The reason is that the only thing this method does  is firing property changes, and this in general has
		// to be done without locked mutexes (as every notification to external listeners).
		// 82300 - 12/21/00 - FS
		updateFromModel();

		xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );

		setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );

		if( aComponentInfos.bVisible && !bDesignMode )
			// Erst nach dem setzen der Daten anzeigen
			xWindow->setVisible( aComponentInfos.bVisible );

		if( !aComponentInfos.bEnable )
			xWindow->setEnable( aComponentInfos.bEnable );

		xView->setGraphics( xGraphics );

		peerCreated();

		mbCreatingPeer = sal_False;
	}
}

Reference< XWindowPeer > UnoControl::getPeer() throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
	return mxPeer;
}

sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );

	// query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
	Reference< XPropertiesChangeListener > xListener;
	queryInterface( ::getCppuType( &xListener ) ) >>= xListener;

	if( xPropSet.is() )
		xPropSet->removePropertiesChangeListener( xListener );

	mpData->bLocalizationSupport = false;
	mxModel = rxModel;

	if( mxModel.is() )
	{
		try
		{
			xPropSet.set( mxModel, UNO_QUERY_THROW );
			Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );

			Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
			xPropSet->addPropertiesChangeListener( aNames, xListener );

			mpData->bLocalizationSupport = xPSI->hasPropertyByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceResolver" ) ) );
		}
		catch( const Exception& )
		{
		DBG_UNHANDLED_EXCEPTION();
			mxModel.clear();
		}
	}

	return mxModel.is();
}

Reference< XControlModel > UnoControl::getModel(	) throw(RuntimeException)
{
	return mxModel;
}

Reference< XView > UnoControl::getView(  ) throw(RuntimeException)
{
	return	static_cast< XView* >( this );
}

void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
{
	ModeChangeEvent aModeChangeEvent;

	Reference< XWindow > xWindow;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		if ( bOn == mbDesignMode )
			return;

		// remember this
		mbDesignMode = bOn;
		xWindow = xWindow.query( getPeer() );
		// dispose our current AccessibleContext, if we have one
		// (changing the design mode implies having a new implementation for this context,
		// so the old one must be declared DEFUNC)
		disposeAccessibleContext();

		aModeChangeEvent.Source = *this;
		aModeChangeEvent.NewMode = ::rtl::OUString::createFromAscii( mbDesignMode ? "design" : "alive" );
	}

	// adjust the visibility of our window
	if ( xWindow.is() )
		xWindow->setVisible( !bOn );

	// and notify our mode listeners
	maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
}

sal_Bool UnoControl::isDesignMode(	) throw(RuntimeException)
{
	return mbDesignMode;
}

sal_Bool UnoControl::isTransparent(  ) throw(RuntimeException)
{
	return sal_False;
}

// XServiceInfo
::rtl::OUString UnoControl::getImplementationName(	) throw(RuntimeException)
{
	DBG_ERROR( "This method should be overloaded!" );
	return ::rtl::OUString();
}

sal_Bool UnoControl::supportsService( const ::rtl::OUString& rServiceName ) throw(RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );

	Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames();
	const ::rtl::OUString* pArray = aSNL.getConstArray();
	const ::rtl::OUString* pArrayEnd = aSNL.getConstArray() + aSNL.getLength();
	for (; pArray != pArrayEnd; ++pArray )
		if( *pArray == rServiceName )
			break;

	return pArray != pArrayEnd;
}

Sequence< ::rtl::OUString > UnoControl::getSupportedServiceNames(  ) throw(RuntimeException)
{
	::rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) );
	return Sequence< ::rtl::OUString >( &sName, 1 );
}

// ------------------------------------------------------------------------
Reference< XAccessibleContext > SAL_CALL UnoControl::getAccessibleContext(  ) throw (RuntimeException)
{
	// creation of the context will certainly require the SolarMutex ...
	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
	::osl::MutexGuard aGuard( GetMutex() );

	Reference< XAccessibleContext > xCurrentContext( maAccessibleContext.get(), UNO_QUERY );
	if ( !xCurrentContext.is() )
	{
		if ( !mbDesignMode )
		{	// in alive mode, use the AccessibleContext of the peer
			Reference< XAccessible > xPeerAcc( getPeer(), UNO_QUERY );
			if ( xPeerAcc.is() )
				xCurrentContext = xPeerAcc->getAccessibleContext( );
		}
		else
			// in design mode, use a fallback
			xCurrentContext = ::toolkit::OAccessibleControlContext::create( this );

		DBG_ASSERT( xCurrentContext.is(), "UnoControl::getAccessibleContext: invalid context (invalid peer?)!" );
		maAccessibleContext = xCurrentContext;

		// get notified when the context is disposed
		Reference< XComponent > xContextComp( xCurrentContext, UNO_QUERY );
		if ( xContextComp.is() )
			xContextComp->addEventListener( this );
		// In an ideal world, this is not necessary - there the object would be released as soon as it has been
		// disposed, and thus our weak reference would be empty, too.
		// But 'til this ideal world comes (means 'til we do never have any refcount/lifetime bugs anymore), we
		// need to listen for disposal and reset our weak reference then.
	}

	return xCurrentContext;
}

void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
	maModeChangeListeners.addInterface( _rxListener );
}

void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
	maModeChangeListeners.removeInterface( _rxListener );
}

void SAL_CALL UnoControl::addModeChangeApproveListener( const Reference< XModeChangeApproveListener >& ) throw (NoSupportException, RuntimeException)
{
	throw NoSupportException( );
}

void SAL_CALL UnoControl::removeModeChangeApproveListener( const Reference< XModeChangeApproveListener >&  ) throw (NoSupportException, RuntimeException)
{
	throw NoSupportException( );
}

//----------------------------------------------------------------------------------------------------------------------
awt::Point SAL_CALL UnoControl::convertPointToLogic( const awt::Point& i_Point, ::sal_Int16 i_TargetUnit ) throw (IllegalArgumentException, RuntimeException)
{
	Reference< XUnitConversion > xPeerConversion;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerConversion = xPeerConversion.query( getPeer() );
	}
	if ( xPeerConversion.is() )
		return xPeerConversion->convertPointToLogic( i_Point, i_TargetUnit );
	return awt::Point( );
}

//----------------------------------------------------------------------------------------------------------------------
awt::Point SAL_CALL UnoControl::convertPointToPixel( const awt::Point& i_Point, ::sal_Int16 i_SourceUnit ) throw (IllegalArgumentException, RuntimeException)
{
	Reference< XUnitConversion > xPeerConversion;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerConversion = xPeerConversion.query( getPeer() );
	}
	if ( xPeerConversion.is() )
		return xPeerConversion->convertPointToPixel( i_Point, i_SourceUnit );
	return awt::Point( );
}

//----------------------------------------------------------------------------------------------------------------------
awt::Size SAL_CALL UnoControl::convertSizeToLogic( const awt::Size& i_Size, ::sal_Int16 i_TargetUnit ) throw (IllegalArgumentException, RuntimeException)
{
	Reference< XUnitConversion > xPeerConversion;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerConversion = xPeerConversion.query( getPeer() );
	}
	if ( xPeerConversion.is() )
		return xPeerConversion->convertSizeToLogic( i_Size, i_TargetUnit );
	return awt::Size( );
}

//----------------------------------------------------------------------------------------------------------------------
awt::Size SAL_CALL UnoControl::convertSizeToPixel( const awt::Size& i_Size, ::sal_Int16 i_SourceUnit ) throw (IllegalArgumentException, RuntimeException)
{
	Reference< XUnitConversion > xPeerConversion;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerConversion = xPeerConversion.query( getPeer() );
	}
	if ( xPeerConversion.is() )
		return xPeerConversion->convertSizeToPixel( i_Size, i_SourceUnit );
	return awt::Size( );
}

//----------------------------------------------------------------------------------------------------------------------
uno::Reference< awt::XStyleSettings > SAL_CALL UnoControl::getStyleSettings() throw (RuntimeException)
{
	Reference< awt::XStyleSettingsSupplier > xPeerSupplier;
	{
		::osl::MutexGuard aGuard( GetMutex() );
		xPeerSupplier = xPeerSupplier.query( getPeer() );
	}
	if ( xPeerSupplier.is() )
		return xPeerSupplier->getStyleSettings();
	return NULL;
}

/* vim: set noet sw=4 ts=4: */
