/**************************************************************
 * 
 * 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 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 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 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" );
	}

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