/**************************************************************
 * 
 * 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 uebertragen
	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 abhaengen erst hinterher einstellen,
				// weil sie von anderen Properties abhaengig sind, die aber erst spaeter
				// 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 theadsafe ....
				// #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 attemp 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 Moeglichkeit 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 ususally
		// 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" );
	}

	// ajust 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;
}
