/**************************************************************
 * 
 * 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/XTextArea.hpp>
#include <com/sun/star/awt/XVclWindowPeer.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/VisualEffect.hpp>
#include <com/sun/star/awt/LineEndFormat.hpp>
#include <com/sun/star/graphic/XGraphicProvider.hpp>
#include <com/sun/star/graphic/GraphicObject.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/awt/ImageScaleMode.hpp>


#include <toolkit/controls/formattedcontrol.hxx>
#include <toolkit/controls/roadmapcontrol.hxx>
#include <toolkit/controls/unocontrols.hxx>
#include <toolkit/controls/stdtabcontroller.hxx>
#include <toolkit/helper/property.hxx>
#include <toolkit/helper/unopropertyarrayhelper.hxx>
#include <toolkit/helper/unomemorystream.hxx>
#include <toolkit/helper/servicenames.hxx>
#include <toolkit/helper/macros.hxx>
#include <toolkit/helper/imagealign.hxx>

// for introspection
#include <toolkit/awt/vclxwindows.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <comphelper/componentcontext.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/extract.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/svapp.hxx>
#include <vcl/edit.hxx>
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#include <vcl/group.hxx>
#include <vcl/fixed.hxx>
#include <vcl/lstbox.hxx>
#include <vcl/combobox.hxx>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <tools/date.hxx>
#include <tools/time.hxx>

#include <algorithm>
#include <functional>

using namespace ::com::sun::star;
using ::com::sun::star::graphic::XGraphic;
using ::com::sun::star::uno::Reference;
using namespace ::toolkit;

#define IMPL_SERVICEINFO_DERIVED( ImplName, BaseClass, ServiceName ) \
    ::rtl::OUString SAL_CALL ImplName::getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException) { return ::rtl::OUString::createFromAscii( "stardiv.Toolkit." #ImplName ); } \
    ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL ImplName::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException)	\
							{ \
								::com::sun::star::uno::Sequence< ::rtl::OUString > aNames = BaseClass::getSupportedServiceNames( ); \
								aNames.realloc( aNames.getLength() + 1 ); \
								aNames[ aNames.getLength() - 1 ] = ::rtl::OUString::createFromAscii( ServiceName ); \
								return aNames; \
							} \



//	----------------------------------------------------
//	class UnoControlEditModel
//	----------------------------------------------------
UnoControlEditModel::UnoControlEditModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXEdit );
}

::rtl::OUString UnoControlEditModel::getServiceName( ) throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlEditModel );
}

uno::Any UnoControlEditModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    uno::Any aReturn;

    switch ( nPropId )
    {
    case BASEPROPERTY_LINE_END_FORMAT:
        aReturn <<= (sal_Int16)awt::LineEndFormat::LINE_FEED;   // LF
        break;
    case BASEPROPERTY_DEFAULTCONTROL:
        aReturn <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlEdit );
        break;
    default:
        aReturn = UnoControlModel::ImplGetDefaultValue( nPropId );
        break;
    }
	return aReturn;
}

::cppu::IPropertyArrayHelper& UnoControlEditModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlEditModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}


//	----------------------------------------------------
//	class UnoEditControl
//	----------------------------------------------------
UnoEditControl::UnoEditControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
    ,maTextListeners( *this )
	,mnMaxTextLen( 0 )
	,mbSetTextInPeer( sal_False )
	,mbSetMaxTextLenInPeer( sal_False )
    ,mbHasTextProperty( sal_False )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
	mnMaxTextLen = 0;
	mbSetMaxTextLenInPeer = sal_False;
}

uno::Any SAL_CALL UnoEditControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
    uno::Any aReturn = UnoControlBase::queryAggregation( rType );
    if ( !aReturn.hasValue() )
        aReturn = UnoEditControl_Base::queryInterface( rType );
    return aReturn;
}

uno::Any SAL_CALL UnoEditControl::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
{
    return UnoControlBase::queryInterface( rType );
}

void SAL_CALL UnoEditControl::acquire(  ) throw ()
{
    UnoControlBase::acquire();
}

void SAL_CALL UnoEditControl::release(  ) throw ()
{
    UnoControlBase::release();
}

IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoEditControl, UnoControlBase, UnoEditControl_Base )

::rtl::OUString UnoEditControl::GetComponentServiceName()
{
    // by default, we want a simple edit field
	::rtl::OUString sName( ::rtl::OUString::createFromAscii( "Edit" ) );

    // but maybe we are to display multi-line text?
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_MULTILINE ) );
	sal_Bool b = sal_Bool();
	if ( ( aVal >>= b ) && b )
		sName= ::rtl::OUString::createFromAscii( "MultiLineEdit" );

	return sName;
}

sal_Bool SAL_CALL UnoEditControl::setModel(const uno::Reference< awt::XControlModel >& _rModel) throw ( uno::RuntimeException )
{
    sal_Bool bReturn = UnoControlBase::setModel( _rModel );
    mbHasTextProperty = ImplHasProperty( BASEPROPERTY_TEXT );
    return bReturn;
}

void UnoEditControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const uno::Any& rVal )
{
    sal_Bool bDone = sal_False;
    if ( GetPropertyId( rPropName ) == BASEPROPERTY_TEXT )
	{
        // #96986# use setText(), or text listener will not be called.
        uno::Reference < awt::XTextComponent > xTextComponent( getPeer(), uno::UNO_QUERY );
        if ( xTextComponent.is() )
        {
            ::rtl::OUString sText;
            rVal >>= sText;
            ImplCheckLocalize( sText );
            xTextComponent->setText( sText );
            bDone = sal_True;
        }
	}

    if ( !bDone )
		UnoControlBase::ImplSetPeerProperty( rPropName, rVal );
}

void UnoEditControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt( *this );
	maTextListeners.disposeAndClear( aEvt );
	UnoControl::dispose();
}

void UnoEditControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
    if ( xText.is() )
    {
	xText->addTextListener( this );

	if ( mbSetMaxTextLenInPeer )
		xText->setMaxTextLen( mnMaxTextLen );
	if ( mbSetTextInPeer )
		xText->setText( maText );
    }
}

void UnoEditControl::textChanged(const awt::TextEvent& e) throw(uno::RuntimeException)
{
	uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );

	if ( mbHasTextProperty )
	{
		uno::Any aAny;
		aAny <<= xText->getText();
		ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), aAny, sal_False );
	}
	else
	{
		maText = xText->getText();
	}

	if ( maTextListeners.getLength() )
		maTextListeners.textChanged( e );
}

void UnoEditControl::addTextListener(const uno::Reference< awt::XTextListener > & l) throw(uno::RuntimeException)
{
	maTextListeners.addInterface( l );
}

void UnoEditControl::removeTextListener(const uno::Reference< awt::XTextListener > & l) throw(uno::RuntimeException)
{
	maTextListeners.removeInterface( l );
}

void UnoEditControl::setText( const ::rtl::OUString& aText ) throw(uno::RuntimeException)
{
	if ( mbHasTextProperty )
	{
		uno::Any aAny;
		aAny <<= aText;
		ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), aAny, sal_True );
	}
	else
	{
		maText = aText;
		mbSetTextInPeer = sal_True;
			uno::Reference < awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
		if ( xText.is() )
			xText->setText( maText );
		}

    // Setting the property to the VCLXWindow doesn't call textChanged
    if ( maTextListeners.getLength() )
    {
        awt::TextEvent aEvent;
        aEvent.Source = *this;
		maTextListeners.textChanged( aEvent );
    }
}

namespace
{
    static void lcl_normalize( awt::Selection& _rSel )
    {
        if ( _rSel.Min > _rSel.Max )
            ::std::swap( _rSel.Min, _rSel.Max );
    }

/*
    static bool lcl_intersect( const awt::Selection& _rLHS, const awt::Selection& _rRHS )
    {
        OSL_PRECOND( _rLHS.Min <= _rLHS.Max, "lcl_intersect: LHS to be normalized!" );
        OSL_PRECOND( _rRHS.Min <= _rRHS.Max, "lcl_intersect: RHS to be normalized!" );
        return !( ( _rLHS.Max < _rRHS.Min ) || ( _rLHS.Min > _rRHS.Max ) );
    }
*/
}

void UnoEditControl::insertText( const awt::Selection& rSel, const ::rtl::OUString& rNewText ) throw(uno::RuntimeException)
{
    // normalize the selection - OUString::replaceAt has a strange behaviour if the min is greater than the max
    awt::Selection aSelection( rSel );
    lcl_normalize( aSelection );

    // preserve the selection resp. cursor position
    awt::Selection aNewSelection( getSelection() );
#ifdef ALSO_PRESERVE_COMPLETE_SELECTION
        // (not sure - looks uglier ...)
    sal_Int32 nDeletedCharacters = ( aSelection.Max - aSelection.Min ) - rNewText.getLength();
    if ( aNewSelection.Min > aSelection.Min )
        aNewSelection.Min -= nDeletedCharacters;
    if ( aNewSelection.Max > aSelection.Max )
        aNewSelection.Max -= nDeletedCharacters;
#else
    aNewSelection.Max = ::std::min( aNewSelection.Min, aNewSelection.Max ) + rNewText.getLength();
    aNewSelection.Min = aNewSelection.Max;
#endif

    ::rtl::OUString aOldText = getText();
    ::rtl::OUString  aNewText = aOldText.replaceAt( aSelection.Min, aSelection.Max - aSelection.Min, rNewText );
    setText( aNewText );

    setSelection( aNewSelection );
}

::rtl::OUString UnoEditControl::getText() throw(uno::RuntimeException)
{
	::rtl::OUString aText = maText;

	if ( mbHasTextProperty )
		aText = ImplGetPropertyValue_UString( BASEPROPERTY_TEXT );
    else
    {
		uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
        if ( xText.is() )
            aText = xText->getText();
    }

	return aText;
}

::rtl::OUString UnoEditControl::getSelectedText( void ) throw(uno::RuntimeException)
{
	::rtl::OUString sSelected;
		uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
	if ( xText.is() )
		sSelected = xText->getSelectedText();

    return sSelected;
}

void UnoEditControl::setSelection( const awt::Selection& aSelection ) throw(uno::RuntimeException)
{
		uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
	if ( xText.is() )
		xText->setSelection( aSelection );
}

awt::Selection UnoEditControl::getSelection( void ) throw(uno::RuntimeException)
{
	awt::Selection aSel;
		uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
	if ( xText.is() )
		aSel = xText->getSelection();
	return aSel;
}

sal_Bool UnoEditControl::isEditable( void ) throw(uno::RuntimeException)
{
	return !ImplGetPropertyValue_BOOL( BASEPROPERTY_READONLY );
}

void UnoEditControl::setEditable( sal_Bool bEditable ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Bool)!bEditable;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_READONLY ), aAny, sal_True );
}

sal_Int16 UnoEditControl::getMaxTextLen() throw(uno::RuntimeException)
{
	sal_Int16 nMaxLen = mnMaxTextLen;

	if ( ImplHasProperty( BASEPROPERTY_MAXTEXTLEN ) )
		nMaxLen = ImplGetPropertyValue_INT16( BASEPROPERTY_MAXTEXTLEN );

	return nMaxLen;
}

void UnoEditControl::setMaxTextLen( sal_Int16 nLen ) throw(uno::RuntimeException)
{
	if ( ImplHasProperty( BASEPROPERTY_MAXTEXTLEN) )
	{
		uno::Any aAny;
		aAny <<= (sal_Int16)nLen;
		ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MAXTEXTLEN ), aAny, sal_True );
	}
	else
	{
		mnMaxTextLen = nLen;
		mbSetMaxTextLenInPeer = sal_True;
			uno::Reference < awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
		if ( xText.is() )
			xText->setMaxTextLen( mnMaxTextLen );
	}
}

awt::Size UnoEditControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoEditControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoEditControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

awt::Size UnoEditControl::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize( nCols, nLines );
}

void UnoEditControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines ) throw(uno::RuntimeException)
{
	Impl_getColumnsAndLines( nCols, nLines );
}


//	----------------------------------------------------
//	class UnoControlFileControlModel
//	----------------------------------------------------
UnoControlFileControlModel::UnoControlFileControlModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
	ImplRegisterProperty( BASEPROPERTY_ALIGN );
	ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
	ImplRegisterProperty( BASEPROPERTY_BORDER );
	ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
	ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
	ImplRegisterProperty( BASEPROPERTY_ENABLED );
	ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
	ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
	ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
	ImplRegisterProperty( BASEPROPERTY_HELPURL );
	ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
	ImplRegisterProperty( BASEPROPERTY_READONLY );
	ImplRegisterProperty( BASEPROPERTY_TABSTOP );
	ImplRegisterProperty( BASEPROPERTY_TEXT );
	ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
	ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
    ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
	ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
}

::rtl::OUString UnoControlFileControlModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlFileControlModel );
}

uno::Any UnoControlFileControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlFileControl );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlFileControlModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlFileControlModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//	class UnoFileControl
//	----------------------------------------------------
UnoFileControl::UnoFileControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoEditControl( i_factory )
{
}

::rtl::OUString UnoFileControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "filecontrol" );
}

//	----------------------------------------------------
//	class GraphicControlModel
//	----------------------------------------------------
uno::Any GraphicControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    if ( nPropId == BASEPROPERTY_GRAPHIC )
        return uno::makeAny( uno::Reference< graphic::XGraphic >() );

    return UnoControlModel::ImplGetDefaultValue( nPropId );
}
    uno::Reference< graphic::XGraphic > GraphicControlModel::getGraphicFromURL_nothrow( const ::rtl::OUString& _rURL )
    {
        uno::Reference< graphic::XGraphic > xGraphic;

        if( ( _rURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 ) )
        {
            // graphic manager uniqueid
            rtl::OUString sID = _rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 );
            // get the DefaultContext
            mxGrfObj = graphic::GraphicObject::createWithId( maContext.getUNOContext(), sID );
        }
        else // linked
            mxGrfObj = NULL; // release the GraphicObject

        if ( !_rURL.getLength() )
            return xGraphic;

        try
        {
            uno::Reference< graphic::XGraphicProvider > xProvider;
            if ( maContext.createComponent( "com.sun.star.graphic.GraphicProvider", xProvider ) )
            {
                uno::Sequence< beans::PropertyValue > aMediaProperties(1);
                aMediaProperties[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
                aMediaProperties[0].Value <<= _rURL;
                xGraphic = xProvider->queryGraphic( aMediaProperties );
            }
        }
        catch( const Exception& )
        {
        	DBG_UNHANDLED_EXCEPTION();
        }

        return xGraphic;
    }

void SAL_CALL GraphicControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::uno::Exception)
{
    UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );

    // - ImageAlign and ImagePosition need to correspond to each other
    // - Graphic and ImageURL need to correspond to each other
    try
    {
        switch ( nHandle )
        {
        case BASEPROPERTY_IMAGEURL:
            if ( !mbAdjustingGraphic && ImplHasProperty( BASEPROPERTY_GRAPHIC ) )
            {
                mbAdjustingGraphic = true;
                ::rtl::OUString sImageURL;
                OSL_VERIFY( rValue >>= sImageURL );
                setDependentFastPropertyValue( BASEPROPERTY_GRAPHIC, uno::makeAny( getGraphicFromURL_nothrow( sImageURL ) ) );
                mbAdjustingGraphic = false;
            }
            break;

        case BASEPROPERTY_GRAPHIC:
            if ( !mbAdjustingGraphic && ImplHasProperty( BASEPROPERTY_IMAGEURL ) )
            {
                mbAdjustingGraphic = true;
                setDependentFastPropertyValue( BASEPROPERTY_IMAGEURL, uno::makeAny( ::rtl::OUString() ) );
                mbAdjustingGraphic = false;
            }
            break;

        case BASEPROPERTY_IMAGEALIGN:
            if ( !mbAdjustingImagePosition && ImplHasProperty( BASEPROPERTY_IMAGEPOSITION ) )
            {
                mbAdjustingImagePosition = true;
                sal_Int16 nUNOValue = 0;
                OSL_VERIFY( rValue >>= nUNOValue );
                setDependentFastPropertyValue( BASEPROPERTY_IMAGEPOSITION, uno::makeAny( getExtendedImagePosition( nUNOValue ) ) );
                mbAdjustingImagePosition = false;
            }
            break;
        case BASEPROPERTY_IMAGEPOSITION:
            if ( !mbAdjustingImagePosition && ImplHasProperty( BASEPROPERTY_IMAGEALIGN ) )
            {
                mbAdjustingImagePosition = true;
                sal_Int16 nUNOValue = 0;
                OSL_VERIFY( rValue >>= nUNOValue );
                setDependentFastPropertyValue( BASEPROPERTY_IMAGEALIGN, uno::makeAny( getCompatibleImageAlign( translateImagePosition( nUNOValue ) ) ) );
                mbAdjustingImagePosition = false;
            }
            break;
        }
    }
    catch( const ::com::sun::star::uno::Exception& )
    {
        OSL_ENSURE( sal_False, "GraphicControlModel::setFastPropertyValue_NoBroadcast: caught an exception while aligning the ImagePosition/ImageAlign properties!" );
        mbAdjustingImagePosition = sal_False;
    }
}

//	----------------------------------------------------
//	class UnoControlButtonModel
//	----------------------------------------------------
UnoControlButtonModel::UnoControlButtonModel( const Reference< XMultiServiceFactory >& i_factory )
    :GraphicControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXButton );

    osl_incrementInterlockedCount( &m_refCount );
    {
        setFastPropertyValue_NoBroadcast( BASEPROPERTY_IMAGEPOSITION, ImplGetDefaultValue( BASEPROPERTY_IMAGEPOSITION ) );
        // this ensures that our ImagePosition is consistent with our ImageAlign property (since both
        // defaults are not per se consistent), since both are coupled in setFastPropertyValue_NoBroadcast
    }
    osl_decrementInterlockedCount( &m_refCount );
}

::rtl::OUString UnoControlButtonModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlButtonModel );
}

uno::Any UnoControlButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    switch ( nPropId )
    {
    case BASEPROPERTY_DEFAULTCONTROL:
        return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoControlButton ) );
    case BASEPROPERTY_TOGGLE:
        return uno::makeAny( (sal_Bool)sal_False );
    case BASEPROPERTY_ALIGN:
        return uno::makeAny( (sal_Int16)PROPERTY_ALIGN_CENTER );
    case BASEPROPERTY_FOCUSONCLICK:
        return uno::makeAny( (sal_Bool)sal_True );
    }

    return GraphicControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlButtonModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlButtonModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//	class UnoButtonControl
//	----------------------------------------------------
UnoButtonControl::UnoButtonControl( const uno::Reference< lang::XMultiServiceFactory >& i_factory )
	:UnoButtonControl_Base( i_factory )
    ,maActionListeners( *this )
	,maItemListeners( *this )
{
	maComponentInfos.nWidth = 50;
	maComponentInfos.nHeight = 14;
}

::rtl::OUString UnoButtonControl::GetComponentServiceName()
{
	::rtl::OUString aName( ::rtl::OUString::createFromAscii( "pushbutton" ) );
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_PUSHBUTTONTYPE ) );
	sal_Int16 n = sal_Int16();
	if ( ( aVal >>= n ) && n )
    {
        // Use PushButtonType later when available...
        switch ( n )
        {
            case 1 /*PushButtonType::OK*/:      aName= ::rtl::OUString::createFromAscii( "okbutton" );
                                                break;
            case 2 /*PushButtonType::CANCEL*/:  aName= ::rtl::OUString::createFromAscii( "cancelbutton" );
                                                break;
            case 3 /*PushButtonType::HELP*/:    aName= ::rtl::OUString::createFromAscii( "helpbutton" );
                                                break;
            default:
            {
                DBG_ERROR( "Unknown Button Type!" );
            }
		}
	}
	return aName;
}

void UnoButtonControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maActionListeners.disposeAndClear( aEvt );
	maItemListeners.disposeAndClear( aEvt );
	UnoControlBase::dispose();
}

void UnoButtonControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoControlBase::createPeer( rxToolkit, rParentPeer );

    uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
	xButton->setActionCommand( maActionCommand );
	if ( maActionListeners.getLength() )
		xButton->addActionListener( &maActionListeners );

    uno::Reference< XToggleButton > xPushButton( getPeer(), uno::UNO_QUERY );
    if ( xPushButton.is() )
        xPushButton->addItemListener( this );
}

void UnoButtonControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	maActionListeners.addInterface( l );
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->addActionListener( &maActionListeners );
	}
}

void UnoButtonControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->removeActionListener( &maActionListeners );
	}
	maActionListeners.removeInterface( l );
}

void UnoButtonControl::addItemListener(const uno::Reference< awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.addInterface( l );
}

void UnoButtonControl::removeItemListener(const uno::Reference< awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.removeInterface( l );
}

void SAL_CALL UnoButtonControl::disposing( const lang::EventObject& Source ) throw (uno::RuntimeException)
{
    UnoControlBase::disposing( Source );
}

void SAL_CALL UnoButtonControl::itemStateChanged( const awt::ItemEvent& rEvent ) throw (uno::RuntimeException)
{
    // forward to model
	uno::Any aAny;
	aAny <<= (sal_Int16)rEvent.Selected;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), aAny, sal_False );

    // multiplex
    ItemEvent aEvent( rEvent );
    aEvent.Source = *this;
    maItemListeners.itemStateChanged( aEvent );
}

void UnoButtonControl::setLabel( const ::rtl::OUString&  rLabel ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= rLabel;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), aAny, sal_True );
}

void UnoButtonControl::setActionCommand( const ::rtl::OUString& rCommand ) throw(uno::RuntimeException)
{
	maActionCommand = rCommand;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->setActionCommand( rCommand );
	}
}

awt::Size UnoButtonControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoButtonControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoButtonControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

//	----------------------------------------------------
//	class UnoControlImageControlModel
//	----------------------------------------------------
UnoControlImageControlModel::UnoControlImageControlModel( const Reference< XMultiServiceFactory >& i_factory )
    :GraphicControlModel( i_factory )
    ,mbAdjustingImageScaleMode( false )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXImageControl );
}

::rtl::OUString UnoControlImageControlModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlImageControlModel );
}

uno::Any UnoControlImageControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
        return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoControlImageControl ) );

    if ( nPropId == BASEPROPERTY_IMAGE_SCALE_MODE )
        return makeAny( awt::ImageScaleMode::Anisotropic );

	return GraphicControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlImageControlModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlImageControlModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

void SAL_CALL UnoControlImageControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::Exception)
{
    GraphicControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );

    // ScaleImage is an older (and less powerful) version of ScaleMode, but keep both in sync as far as possible
    try
    {
        switch ( _nHandle )
        {
        case BASEPROPERTY_IMAGE_SCALE_MODE:
            if ( !mbAdjustingImageScaleMode && ImplHasProperty( BASEPROPERTY_SCALEIMAGE ) )
            {
                mbAdjustingImageScaleMode = true;
                sal_Int16 nScaleMode( awt::ImageScaleMode::Anisotropic );
                OSL_VERIFY( _rValue >>= nScaleMode );
                setDependentFastPropertyValue( BASEPROPERTY_SCALEIMAGE, uno::makeAny( sal_Bool( nScaleMode != awt::ImageScaleMode::None ) ) );
                mbAdjustingImageScaleMode = false;
            }
            break;
        case BASEPROPERTY_SCALEIMAGE:
            if ( !mbAdjustingImageScaleMode && ImplHasProperty( BASEPROPERTY_IMAGE_SCALE_MODE ) )
            {
                mbAdjustingImageScaleMode = true;
                sal_Bool bScale = sal_True;
                OSL_VERIFY( _rValue >>= bScale );
                setDependentFastPropertyValue( BASEPROPERTY_IMAGE_SCALE_MODE, uno::makeAny( bScale ? awt::ImageScaleMode::Anisotropic : awt::ImageScaleMode::None ) );
                mbAdjustingImageScaleMode = false;
            }
            break;
        }
    }
    catch( const Exception& )
    {
        mbAdjustingImageScaleMode = false;
        throw;
    }
}

//	----------------------------------------------------
//	class UnoImageControlControl
//	----------------------------------------------------
UnoImageControlControl::UnoImageControlControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoImageControlControl_Base( i_factory )
    ,maActionListeners( *this )
{
	// Woher die Defaults nehmen?
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 100;
}

::rtl::OUString UnoImageControlControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "fixedimage" );
}

void UnoImageControlControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maActionListeners.disposeAndClear( aEvt );
	UnoControl::dispose();
}

sal_Bool UnoImageControlControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

awt::Size UnoImageControlControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoImageControlControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoImageControlControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

//	----------------------------------------------------
//	class UnoControlRadioButtonModel
//	----------------------------------------------------
UnoControlRadioButtonModel::UnoControlRadioButtonModel( const Reference< XMultiServiceFactory >& i_factory )
    :GraphicControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXRadioButton );
}

::rtl::OUString UnoControlRadioButtonModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlRadioButtonModel );
}

uno::Any UnoControlRadioButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    switch ( nPropId )
    {
    case BASEPROPERTY_DEFAULTCONTROL:
        return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoControlRadioButton ) );

    case BASEPROPERTY_VISUALEFFECT:
        return uno::makeAny( (sal_Int16)awt::VisualEffect::LOOK3D );
    }

    return GraphicControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlRadioButtonModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlRadioButtonModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}



//	----------------------------------------------------
//	class UnoRadioButtonControl
//	----------------------------------------------------
UnoRadioButtonControl::UnoRadioButtonControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoRadioButtonControl_Base( i_factory )
    ,maItemListeners( *this )
    ,maActionListeners( *this )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
}

::rtl::OUString UnoRadioButtonControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "radiobutton" );
}

void UnoRadioButtonControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maItemListeners.disposeAndClear( aEvt );
	UnoControlBase::dispose();
}


sal_Bool UnoRadioButtonControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

void UnoRadioButtonControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoControlBase::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XRadioButton >  xRadioButton( getPeer(), uno::UNO_QUERY );
	xRadioButton->addItemListener( this );

	uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
	xButton->setActionCommand( maActionCommand );
	if ( maActionListeners.getLength() )
		xButton->addActionListener( &maActionListeners );

	// as default, set the "AutoToggle" to true
	// (it is set to false in VCLXToolkit::ImplCreateWindow because of #87254#, but we want to
	// have it enabled by default because of 85071)
	uno::Reference< awt::XVclWindowPeer >  xVclWindowPeer( getPeer(), uno::UNO_QUERY );
	if ( xVclWindowPeer.is() )
		xVclWindowPeer->setProperty( GetPropertyName( BASEPROPERTY_AUTOTOGGLE ), ::cppu::bool2any( sal_True ) );
}

void UnoRadioButtonControl::addItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.addInterface( l );
}

void UnoRadioButtonControl::removeItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.removeInterface( l );
}

void UnoRadioButtonControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	maActionListeners.addInterface( l );
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->addActionListener( &maActionListeners );
	}
}

void UnoRadioButtonControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->removeActionListener( &maActionListeners );
	}
	maActionListeners.removeInterface( l );
}

void UnoRadioButtonControl::setLabel( const ::rtl::OUString&  rLabel ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= rLabel;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), aAny, sal_True );
}

void UnoRadioButtonControl::setActionCommand( const ::rtl::OUString& rCommand ) throw(uno::RuntimeException)
{
	maActionCommand = rCommand;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->setActionCommand( rCommand );
	}
}

void UnoRadioButtonControl::setState( sal_Bool bOn ) throw(uno::RuntimeException)
{
	sal_Int16 nState = bOn ? 1 : 0;
	uno::Any aAny;
	aAny <<= nState;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), aAny, sal_True );
}

sal_Bool UnoRadioButtonControl::getState() throw(uno::RuntimeException)
{
	sal_Int16 nState = 0;
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ) );
	aVal >>= nState;
	return nState ? sal_True : sal_False;
}

void UnoRadioButtonControl::itemStateChanged( const awt::ItemEvent& rEvent ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Int16)rEvent.Selected;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), aAny, sal_False );

    // compatibility:
    // in OOo 1.0.x, when the user clicked a radio button in a group of buttons, this resulted
    // in _one_ itemStateChanged call for exactly the radio button which's state changed from
    // "0" to "1".
    // Nowadays, since the listener handling changed a lot towards 1.1 (the VCLXWindow reacts on more
    // basic events from the VCL-windows, not anymore on the Link-based events like in 1.0.x), this
    // isn't the case anymore: For instance, this method here gets called for the radio button
    // which is being implicitily _de_selected, too. This is pretty bad for compatibility.
    // Thus, we suppress all events with a new state other than "1". This is unlogical, and weird, when looking
    // from a pure API perspective, but it's _compatible_ with older product versions, and this is
    // all which matters here.
    // #i14703# - 2003-05-23 - fs@openoffice.org
    if ( 1 == rEvent.Selected )
    {
    	if ( maItemListeners.getLength() )
	    	maItemListeners.itemStateChanged( rEvent );
    }
        // note that speaking stricly, this is wrong: When in 1.0.x, the user would have de-selected
        // a radio button _without_ selecing another one, this would have caused a notification.
        // With the change done here, this today won't cause a notification anymore.
        //
        // Fortunately, it's not possible for the user to de-select a radio button without selecting another on,
        // at least not via the regular UI. It _would_ be possible via the Accessibility API, which
        // counts as "user input", too. But in 1.0.x, there was no Accessibility API, so there is nothing
        // to be inconsistent with.
}

awt::Size UnoRadioButtonControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoRadioButtonControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoRadioButtonControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

//	----------------------------------------------------
//	class UnoControlCheckBoxModel
//	----------------------------------------------------
UnoControlCheckBoxModel::UnoControlCheckBoxModel( const Reference< XMultiServiceFactory >& i_factory )
    :GraphicControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXCheckBox );
}

::rtl::OUString UnoControlCheckBoxModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlCheckBoxModel );
}

uno::Any UnoControlCheckBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    switch ( nPropId )
    {
    case BASEPROPERTY_DEFAULTCONTROL:
        return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoControlCheckBox ) );

    case BASEPROPERTY_VISUALEFFECT:
        return uno::makeAny( (sal_Int16)awt::VisualEffect::LOOK3D );
    }

    return GraphicControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlCheckBoxModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlCheckBoxModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}



//	----------------------------------------------------
//	class UnoCheckBoxControl
//	----------------------------------------------------
UnoCheckBoxControl::UnoCheckBoxControl( const uno::Reference< lang::XMultiServiceFactory >& i_factory )
	:UnoCheckBoxControl_Base( i_factory )
    ,maItemListeners( *this ), maActionListeners( *this )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
}

::rtl::OUString UnoCheckBoxControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "checkbox" );
}

void UnoCheckBoxControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maItemListeners.disposeAndClear( aEvt );
	UnoControlBase::dispose();
}

sal_Bool UnoCheckBoxControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

void UnoCheckBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoControlBase::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XCheckBox >  xCheckBox( getPeer(), uno::UNO_QUERY );
	xCheckBox->addItemListener( this );

	uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
	xButton->setActionCommand( maActionCommand );
	if ( maActionListeners.getLength() )
		xButton->addActionListener( &maActionListeners );
}

void UnoCheckBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.addInterface( l );
}

void UnoCheckBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.removeInterface( l );
}

void UnoCheckBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	maActionListeners.addInterface( l );
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->addActionListener( &maActionListeners );
	}
}

void UnoCheckBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XButton >  xButton( getPeer(), uno::UNO_QUERY );
		xButton->removeActionListener( &maActionListeners );
	}
	maActionListeners.removeInterface( l );
}

void UnoCheckBoxControl::setActionCommand( const ::rtl::OUString& rCommand ) throw(uno::RuntimeException)
{
	maActionCommand = rCommand;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
		xButton->setActionCommand( rCommand );
	}
}


void UnoCheckBoxControl::setLabel( const ::rtl::OUString&  rLabel ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= rLabel;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), aAny, sal_True );
}

void UnoCheckBoxControl::setState( short n ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Int16)n;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), aAny, sal_True );
}

short UnoCheckBoxControl::getState() throw(uno::RuntimeException)
{
	short nState = 0;
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ) );
	aVal >>= nState;
	return nState;
}

void UnoCheckBoxControl::enableTriState( sal_Bool b ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= b;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TRISTATE ), aAny, sal_True );
}

void UnoCheckBoxControl::itemStateChanged( const awt::ItemEvent& rEvent ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Int16)rEvent.Selected;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), aAny, sal_False );

	if ( maItemListeners.getLength() )
		maItemListeners.itemStateChanged( rEvent );
}

awt::Size UnoCheckBoxControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoCheckBoxControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoCheckBoxControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

//	----------------------------------------------------
//  class UnoControlFixedHyperlinkModel
//	----------------------------------------------------
UnoControlFixedHyperlinkModel::UnoControlFixedHyperlinkModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXFixedHyperlink );
}

::rtl::OUString UnoControlFixedHyperlinkModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedHyperlinkModel );
}

uno::Any UnoControlFixedHyperlinkModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
        aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedHyperlink );
		return aAny;
	}
	else if ( nPropId == BASEPROPERTY_BORDER )
	{
		uno::Any aAny;
		aAny <<= (sal_Int16)0;
		return aAny;
	}
    else if ( nPropId == BASEPROPERTY_URL )
    {
        uno::Any aAny;
        aAny <<= ::rtl::OUString();
        return aAny;
    }

	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlFixedHyperlinkModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlFixedHyperlinkModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//  class UnoFixedHyperlinkControl
//	----------------------------------------------------
UnoFixedHyperlinkControl::UnoFixedHyperlinkControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
    ,maActionListeners( *this )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
}

::rtl::OUString UnoFixedHyperlinkControl::GetComponentServiceName()
{
    return ::rtl::OUString::createFromAscii( "fixedhyperlink" );
}

// uno::XInterface
uno::Any UnoFixedHyperlinkControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( awt::XFixedHyperlink*, this ),
										SAL_STATIC_CAST( awt::XLayoutConstrains*, this ) );
	return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoFixedHyperlinkControl )
    getCppuType( ( uno::Reference< awt::XFixedHyperlink>* ) NULL ),
	getCppuType( ( uno::Reference< awt::XLayoutConstrains>* ) NULL ),
	UnoControlBase::getTypes()
IMPL_XTYPEPROVIDER_END

sal_Bool UnoFixedHyperlinkControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

void UnoFixedHyperlinkControl::setText( const ::rtl::OUString& Text ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Text;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), aAny, sal_True );
}

::rtl::OUString UnoFixedHyperlinkControl::getText() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_UString( BASEPROPERTY_LABEL );
}

void UnoFixedHyperlinkControl::setURL( const ::rtl::OUString& URL ) throw(::com::sun::star::uno::RuntimeException)
{
    uno::Any aAny;
    aAny <<= URL;
    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_URL ), aAny, sal_True );
}

::rtl::OUString UnoFixedHyperlinkControl::getURL(  ) throw(::com::sun::star::uno::RuntimeException)
{
    return ImplGetPropertyValue_UString( BASEPROPERTY_URL );
}

void UnoFixedHyperlinkControl::setAlignment( short nAlign ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Int16)nAlign;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ), aAny, sal_True );
}

short UnoFixedHyperlinkControl::getAlignment() throw(uno::RuntimeException)
{
	short nAlign = 0;
	if ( mxModel.is() )
	{
		uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ) );
		aVal >>= nAlign;
	}
	return nAlign;
}

awt::Size UnoFixedHyperlinkControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoFixedHyperlinkControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoFixedHyperlinkControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

void UnoFixedHyperlinkControl::dispose() throw(uno::RuntimeException)
{
    lang::EventObject aEvt;
    aEvt.Source = (::cppu::OWeakObject*)this;
    maActionListeners.disposeAndClear( aEvt );
    UnoControlBase::dispose();
}

void UnoFixedHyperlinkControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
    UnoControlBase::createPeer( rxToolkit, rParentPeer );

    uno::Reference < awt::XFixedHyperlink > xFixedHyperlink( getPeer(), uno::UNO_QUERY );
    if ( maActionListeners.getLength() )
        xFixedHyperlink->addActionListener( &maActionListeners );
}

void UnoFixedHyperlinkControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
    maActionListeners.addInterface( l );
    if( getPeer().is() && maActionListeners.getLength() == 1 )
    {
        uno::Reference < awt::XFixedHyperlink >  xFixedHyperlink( getPeer(), uno::UNO_QUERY );
        xFixedHyperlink->addActionListener( &maActionListeners );
    }
}

void UnoFixedHyperlinkControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
    if( getPeer().is() && maActionListeners.getLength() == 1 )
    {
        uno::Reference < awt::XFixedHyperlink >  xFixedHyperlink( getPeer(), uno::UNO_QUERY );
        xFixedHyperlink->removeActionListener( &maActionListeners );
    }
    maActionListeners.removeInterface( l );
}

//  ----------------------------------------------------
//  class UnoControlFixedTextModel
//  ----------------------------------------------------
UnoControlFixedTextModel::UnoControlFixedTextModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXFixedText );
}

::rtl::OUString UnoControlFixedTextModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedTextModel );
}

uno::Any UnoControlFixedTextModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
    if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
    {
        uno::Any aAny;
        aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedText );
        return aAny;
    }
    else if ( nPropId == BASEPROPERTY_BORDER )
    {
        uno::Any aAny;
        aAny <<= (sal_Int16)0;
        return aAny;
    }

    return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlFixedTextModel::getInfoHelper()
{
    static UnoPropertyArrayHelper* pHelper = NULL;
    if ( !pHelper )
    {
        uno::Sequence<sal_Int32>    aIDs = ImplGetPropertyIds();
        pHelper = new UnoPropertyArrayHelper( aIDs );
    }
    return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlFixedTextModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
    static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
    return xInfo;
}


//  ----------------------------------------------------
//  class UnoFixedTextControl
//  ----------------------------------------------------
UnoFixedTextControl::UnoFixedTextControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
{
    maComponentInfos.nWidth = 100;
    maComponentInfos.nHeight = 12;
}

::rtl::OUString UnoFixedTextControl::GetComponentServiceName()
{
    return ::rtl::OUString::createFromAscii( "fixedtext" );
}

// uno::XInterface
uno::Any UnoFixedTextControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
    uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( awt::XFixedText*, this ),
                                        SAL_STATIC_CAST( awt::XLayoutConstrains*, this ) );
    return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoFixedTextControl )
    getCppuType( ( uno::Reference< awt::XFixedText>* ) NULL ),
    getCppuType( ( uno::Reference< awt::XLayoutConstrains>* ) NULL ),
    UnoControlBase::getTypes()
IMPL_XTYPEPROVIDER_END

sal_Bool UnoFixedTextControl::isTransparent() throw(uno::RuntimeException)
{
    return sal_True;
}

void UnoFixedTextControl::setText( const ::rtl::OUString& Text ) throw(uno::RuntimeException)
{
    uno::Any aAny;
    aAny <<= Text;
    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), aAny, sal_True );
}

::rtl::OUString UnoFixedTextControl::getText() throw(uno::RuntimeException)
{
    return ImplGetPropertyValue_UString( BASEPROPERTY_LABEL );
}

void UnoFixedTextControl::setAlignment( short nAlign ) throw(uno::RuntimeException)
{
    uno::Any aAny;
    aAny <<= (sal_Int16)nAlign;
    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ), aAny, sal_True );
}

short UnoFixedTextControl::getAlignment() throw(uno::RuntimeException)
{
    short nAlign = 0;
    if ( mxModel.is() )
    {
        uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ) );
        aVal >>= nAlign;
    }
    return nAlign;
}

awt::Size UnoFixedTextControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
    return Impl_getMinimumSize();
}

awt::Size UnoFixedTextControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
    return Impl_getPreferredSize();
}

awt::Size UnoFixedTextControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
    return Impl_calcAdjustedSize( rNewSize );
}

//	----------------------------------------------------
//	class UnoControlGroupBoxModel
//	----------------------------------------------------
UnoControlGroupBoxModel::UnoControlGroupBoxModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
	ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
	ImplRegisterProperty( BASEPROPERTY_ENABLED );
	ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
	ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
	ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
	ImplRegisterProperty( BASEPROPERTY_HELPURL );
	ImplRegisterProperty( BASEPROPERTY_LABEL );
	ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
	ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
    ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
}

::rtl::OUString UnoControlGroupBoxModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlGroupBoxModel );
}

uno::Any UnoControlGroupBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlGroupBox );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlGroupBoxModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlGroupBoxModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//	class UnoGroupBoxControl
//	----------------------------------------------------
UnoGroupBoxControl::UnoGroupBoxControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 100;
}

::rtl::OUString UnoGroupBoxControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "groupbox" );
}

sal_Bool UnoGroupBoxControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

// =====================================================================================================================
// = UnoControlListBoxModel_Data
// =====================================================================================================================
struct ListItem
{
    ::rtl::OUString ItemText;
    ::rtl::OUString ItemImageURL;
    Any             ItemData;

    ListItem()
        :ItemText()
        ,ItemImageURL()
        ,ItemData()
    {
    }

    ListItem( const ::rtl::OUString& i_rItemText )
        :ItemText( i_rItemText )
        ,ItemImageURL()
        ,ItemData()
    {
    }
};

typedef beans::Pair< ::rtl::OUString, ::rtl::OUString > UnoListItem;

struct StripItemData : public ::std::unary_function< ListItem, UnoListItem >
{
    UnoListItem operator()( const ListItem& i_rItem )
    {
        return UnoListItem( i_rItem.ItemText, i_rItem.ItemImageURL );
    }
};

struct UnoControlListBoxModel_Data
{
    UnoControlListBoxModel_Data( UnoControlListBoxModel& i_rAntiImpl )
        :m_bSettingLegacyProperty( false )
        ,m_rAntiImpl( i_rAntiImpl )
        ,m_aListItems()
    {
    }

    sal_Int32 getItemCount() const { return sal_Int32( m_aListItems.size() ); }

    const ListItem& getItem( const sal_Int32 i_nIndex ) const
    {
        if ( ( i_nIndex < 0 ) || ( i_nIndex >= sal_Int32( m_aListItems.size() ) ) )
            throw IndexOutOfBoundsException( ::rtl::OUString(), m_rAntiImpl );
        return m_aListItems[ i_nIndex ];
    }

    ListItem& getItem( const sal_Int32 i_nIndex )
    {
        return const_cast< ListItem& >( static_cast< const UnoControlListBoxModel_Data* >( this )->getItem( i_nIndex ) );
    }

    ListItem& insertItem( const sal_Int32 i_nIndex )
    {
        if ( ( i_nIndex < 0 ) || ( i_nIndex > sal_Int32( m_aListItems.size() ) ) )
            throw IndexOutOfBoundsException( ::rtl::OUString(), m_rAntiImpl );
        return *m_aListItems.insert( m_aListItems.begin() + i_nIndex, ListItem() );
    }

    Sequence< UnoListItem > getAllItems() const
    {
        Sequence< UnoListItem > aItems( sal_Int32( m_aListItems.size() ) );
        ::std::transform( m_aListItems.begin(), m_aListItems.end(), aItems.getArray(), StripItemData() );
        return aItems;
    }

    void copyItems( const UnoControlListBoxModel_Data& i_copySource )
    {
        m_aListItems = i_copySource.m_aListItems;
    }

    void    setAllItems( const ::std::vector< ListItem >& i_rItems )
    {
        m_aListItems = i_rItems;
    }

    void    removeItem( const sal_Int32 i_nIndex )
    {
        if ( ( i_nIndex < 0 ) || ( i_nIndex >= sal_Int32( m_aListItems.size() ) ) )
            throw IndexOutOfBoundsException( ::rtl::OUString(), m_rAntiImpl );
        m_aListItems.erase( m_aListItems.begin() + i_nIndex );
    }

    void removeAllItems()
    {
        ::std::vector< ListItem > aEmpty;
        m_aListItems.swap( aEmpty );
    }

public:
    bool                        m_bSettingLegacyProperty;

private:
    UnoControlListBoxModel&     m_rAntiImpl;
    ::std::vector< ListItem >   m_aListItems;
};

// =====================================================================================================================
// = UnoControlListBoxModel
// =====================================================================================================================
// ---------------------------------------------------------------------------------------------------------------------
UnoControlListBoxModel::UnoControlListBoxModel( const Reference< XMultiServiceFactory >& i_factory, ConstructorMode const i_mode )
    :UnoControlListBoxModel_Base( i_factory )
    ,m_pData( new UnoControlListBoxModel_Data( *this ) )
    ,m_aItemListListeners( GetMutex() )
{
    if ( i_mode == ConstructDefault )
    {
        UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXListBox );
    }
}
// ---------------------------------------------------------------------------------------------------------------------
UnoControlListBoxModel::UnoControlListBoxModel( const UnoControlListBoxModel& i_rSource )
    :UnoControlListBoxModel_Base( i_rSource )
    ,m_pData( new UnoControlListBoxModel_Data( *this ) )
    ,m_aItemListListeners( GetMutex() )
{
    m_pData->copyItems( *i_rSource.m_pData );
}
UnoControlListBoxModel::~UnoControlListBoxModel()
{
}
IMPL_SERVICEINFO_DERIVED( UnoControlListBoxModel, UnoControlModel, szServiceName2_UnoControlListBoxModel )
// ---------------------------------------------------------------------------------------------------------------------
::rtl::OUString UnoControlListBoxModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlListBoxModel );
}

// ---------------------------------------------------------------------------------------------------------------------
uno::Any UnoControlListBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlListBox );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

// ---------------------------------------------------------------------------------------------------------------------
::cppu::IPropertyArrayHelper& UnoControlListBoxModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// ---------------------------------------------------------------------------------------------------------------------
// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlListBoxModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

// ---------------------------------------------------------------------------------------------------------------------
namespace
{
    struct CreateListItem : public ::std::unary_function< ::rtl::OUString, ListItem >
    {
        ListItem operator()( const ::rtl::OUString& i_rItemText )
        {
            return ListItem( i_rItemText );
        }
    };
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue ) throw (uno::Exception)
{
    UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );

    if ( nHandle == BASEPROPERTY_STRINGITEMLIST )
	{
        // reset selection
		uno::Sequence<sal_Int16> aSeq;
		uno::Any aAny;
		aAny <<= aSeq;
		setDependentFastPropertyValue( BASEPROPERTY_SELECTEDITEMS, aAny );

        if ( !m_pData->m_bSettingLegacyProperty )
        {
            // synchronize the legacy StringItemList property with our list items
            Sequence< ::rtl::OUString > aStringItemList;
            Any aPropValue;
            getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
            OSL_VERIFY( aPropValue >>= aStringItemList );

            ::std::vector< ListItem > aItems( aStringItemList.getLength() );
            ::std::transform(
                aStringItemList.getConstArray(),
                aStringItemList.getConstArray() + aStringItemList.getLength(),
                aItems.begin(),
                CreateListItem()
            );
            m_pData->setAllItems( aItems );

            // since an XItemListListener does not have a "all items modified" or some such method,
            // we simulate this by notifying removal of all items, followed by insertion of all new
            // items
            lang::EventObject aEvent;
            aEvent.Source = *this;
            m_aItemListListeners.notifyEach( &XItemListListener::itemListChanged, aEvent );
            // TODO: OPropertySetHelper calls into this method with the mutex locked ...
            // which is wrong for the above notifications ...
        }
	}
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::ImplNormalizePropertySequence( const sal_Int32 _nCount, sal_Int32* _pHandles,
	uno::Any* _pValues, sal_Int32* _pValidHandles ) const SAL_THROW(())
{
	// dependencies we know:
	// BASEPROPERTY_STRINGITEMLIST->BASEPROPERTY_SELECTEDITEMS
    ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_STRINGITEMLIST, BASEPROPERTY_SELECTEDITEMS );

	UnoControlModel::ImplNormalizePropertySequence( _nCount, _pHandles, _pValues, _pValidHandles );
}

// ---------------------------------------------------------------------------------------------------------------------
::sal_Int32 SAL_CALL UnoControlListBoxModel::getItemCount() throw (RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
    return m_pData->getItemCount();
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::insertItem( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemText, const ::rtl::OUString& i_rItemImageURL ) throw (IndexOutOfBoundsException, RuntimeException)
{
    ::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->insertItem( i_nPosition ) );
    rItem.ItemText = i_rItemText;
    rItem.ItemImageURL = i_rItemImageURL;

    impl_handleInsert( i_nPosition, i_rItemText, i_rItemImageURL, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::insertItemText( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemText ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->insertItem( i_nPosition ) );
    rItem.ItemText = i_rItemText;

    impl_handleInsert( i_nPosition, i_rItemText, ::boost::optional< ::rtl::OUString >(), aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::insertItemImage( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemImageURL ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->insertItem( i_nPosition ) );
    rItem.ItemImageURL = i_rItemImageURL;

    impl_handleInsert( i_nPosition, ::boost::optional< ::rtl::OUString >(), i_rItemImageURL, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::removeItem( ::sal_Int32 i_nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    m_pData->removeItem( i_nPosition );

    impl_handleRemove( i_nPosition, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::removeAllItems(  ) throw (::com::sun::star::uno::RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    m_pData->removeAllItems();

    impl_handleRemove( -1, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::setItemText( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemText ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->getItem( i_nPosition ) );
    rItem.ItemText = i_rItemText;

    impl_handleModify( i_nPosition, i_rItemText, ::boost::optional< ::rtl::OUString >(), aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::setItemImage( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemImageURL ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->getItem( i_nPosition ) );
    rItem.ItemImageURL = i_rItemImageURL;

    impl_handleModify( i_nPosition, ::boost::optional< ::rtl::OUString >(), i_rItemImageURL, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::setItemTextAndImage( ::sal_Int32 i_nPosition, const ::rtl::OUString& i_rItemText, const ::rtl::OUString& i_rItemImageURL ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    // SYNCHRONIZED ----->
    ListItem& rItem( m_pData->getItem( i_nPosition ) );
    rItem.ItemText = i_rItemText;
    rItem.ItemImageURL = i_rItemImageURL;

    impl_handleModify( i_nPosition, i_rItemText, i_rItemImageURL, aGuard );
    // <----- SYNCHRONIZED
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::setItemData( ::sal_Int32 i_nPosition, const Any& i_rDataValue ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    ListItem& rItem( m_pData->getItem( i_nPosition ) );
    rItem.ItemData = i_rDataValue;
}

// ---------------------------------------------------------------------------------------------------------------------
::rtl::OUString SAL_CALL UnoControlListBoxModel::getItemText( ::sal_Int32 i_nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
{
    ::osl::MutexGuard aGuard( GetMutex() );
    const ListItem& rItem( m_pData->getItem( i_nPosition ) );
    return rItem.ItemText;
}

// ---------------------------------------------------------------------------------------------------------------------
::rtl::OUString SAL_CALL UnoControlListBoxModel::getItemImage( ::sal_Int32 i_nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
    const ListItem& rItem( m_pData->getItem( i_nPosition ) );
    return rItem.ItemImageURL;
}

// ---------------------------------------------------------------------------------------------------------------------
beans::Pair< ::rtl::OUString, ::rtl::OUString > SAL_CALL UnoControlListBoxModel::getItemTextAndImage( ::sal_Int32 i_nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
    const ListItem& rItem( m_pData->getItem( i_nPosition ) );
    return beans::Pair< ::rtl::OUString, ::rtl::OUString >( rItem.ItemText, rItem.ItemImageURL );
}

// ---------------------------------------------------------------------------------------------------------------------
Any SAL_CALL UnoControlListBoxModel::getItemData( ::sal_Int32 i_nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::ClearableMutexGuard aGuard( GetMutex() );
    const ListItem& rItem( m_pData->getItem( i_nPosition ) );
    return rItem.ItemData;
}

// ---------------------------------------------------------------------------------------------------------------------
Sequence< beans::Pair< ::rtl::OUString, ::rtl::OUString > > SAL_CALL UnoControlListBoxModel::getAllItems(  ) throw (RuntimeException)
{
	::osl::MutexGuard aGuard( GetMutex() );
    return m_pData->getAllItems();
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::addItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener ) throw (uno::RuntimeException)
{
    if ( i_Listener.is() )
        m_aItemListListeners.addInterface( i_Listener );
}

// ---------------------------------------------------------------------------------------------------------------------
void SAL_CALL UnoControlListBoxModel::removeItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener ) throw (uno::RuntimeException)
{
    if ( i_Listener.is() )
        m_aItemListListeners.removeInterface( i_Listener );
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_getStringItemList( ::std::vector< ::rtl::OUString >& o_rStringItems ) const
{
    Sequence< ::rtl::OUString > aStringItemList;
    Any aPropValue;
    getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
    OSL_VERIFY( aPropValue >>= aStringItemList );

    o_rStringItems.resize( size_t( aStringItemList.getLength() ) );
    ::std::copy(
        aStringItemList.getConstArray(),
        aStringItemList.getConstArray() + aStringItemList.getLength(),
        o_rStringItems.begin()
    );
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_setStringItemList_nolck( const ::std::vector< ::rtl::OUString >& i_rStringItems )
{
    Sequence< ::rtl::OUString > aStringItems( i_rStringItems.size() );
    ::std::copy(
        i_rStringItems.begin(),
        i_rStringItems.end(),
        aStringItems.getArray()
    );
    m_pData->m_bSettingLegacyProperty = true;
    try
    {
        setFastPropertyValue( BASEPROPERTY_STRINGITEMLIST, uno::makeAny( aStringItems ) );
    }
    catch( const Exception& )
    {
        m_pData->m_bSettingLegacyProperty = false;
        throw;
    }
    m_pData->m_bSettingLegacyProperty = false;
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_handleInsert( const sal_Int32 i_nItemPosition, const ::boost::optional< ::rtl::OUString >& i_rItemText,
        const ::boost::optional< ::rtl::OUString >& i_rItemImageURL, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
{
    // SYNCHRONIZED ----->
    // sync with legacy StringItemList property
    ::std::vector< ::rtl::OUString > aStringItems;
    impl_getStringItemList( aStringItems );
    OSL_ENSURE( size_t( i_nItemPosition ) <= aStringItems.size(), "UnoControlListBoxModel::impl_handleInsert" );
    if ( size_t( i_nItemPosition ) <= aStringItems.size() )
    {
        const ::rtl::OUString sItemText( !!i_rItemText ? *i_rItemText : ::rtl::OUString() );
        aStringItems.insert( aStringItems.begin() + i_nItemPosition, sItemText );
    }

    i_rClearBeforeNotify.clear();
    // <----- SYNCHRONIZED
    impl_setStringItemList_nolck( aStringItems );

    // notify ItemListListeners
    impl_notifyItemListEvent_nolck( i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemInserted );
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_handleRemove( const sal_Int32 i_nItemPosition, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
{
    // SYNCHRONIZED ----->
    const bool bAllItems = ( i_nItemPosition < 0 );
    // sync with legacy StringItemList property
    ::std::vector< ::rtl::OUString > aStringItems;
    impl_getStringItemList( aStringItems );
    if ( !bAllItems )
    {
        OSL_ENSURE( size_t( i_nItemPosition ) < aStringItems.size(), "UnoControlListBoxModel::impl_handleRemove" );
        if ( size_t( i_nItemPosition ) < aStringItems.size() )
        {
            aStringItems.erase( aStringItems.begin() + i_nItemPosition );
        }
    }
    else
    {
        aStringItems.resize(0);
    }

    i_rClearBeforeNotify.clear();
    // <----- SYNCHRONIZED
    impl_setStringItemList_nolck( aStringItems );

    // notify ItemListListeners
    if ( bAllItems )
    {
        EventObject aEvent( *this );
        m_aItemListListeners.notifyEach( &XItemListListener::allItemsRemoved, aEvent );
    }
    else
    {
        impl_notifyItemListEvent_nolck( i_nItemPosition, ::boost::optional< ::rtl::OUString >(), ::boost::optional< ::rtl::OUString >(),
            &XItemListListener::listItemRemoved );
    }
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_handleModify( const sal_Int32 i_nItemPosition, const ::boost::optional< ::rtl::OUString >& i_rItemText,
        const ::boost::optional< ::rtl::OUString >& i_rItemImageURL, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
{
    // SYNCHRONIZED ----->
    if ( !!i_rItemText )
    {
        // sync with legacy StringItemList property
        ::std::vector< ::rtl::OUString > aStringItems;
        impl_getStringItemList( aStringItems );
        OSL_ENSURE( size_t( i_nItemPosition ) < aStringItems.size(), "UnoControlListBoxModel::impl_handleModify" );
        if ( size_t( i_nItemPosition ) < aStringItems.size() )
        {
            aStringItems[ i_nItemPosition] = *i_rItemText;
        }

        i_rClearBeforeNotify.clear();
        // <----- SYNCHRONIZED
        impl_setStringItemList_nolck( aStringItems );
    }
    else
    {
        i_rClearBeforeNotify.clear();
        // <----- SYNCHRONIZED
    }

    // notify ItemListListeners
    impl_notifyItemListEvent_nolck( i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemModified );
}

// ---------------------------------------------------------------------------------------------------------------------
void UnoControlListBoxModel::impl_notifyItemListEvent_nolck( const sal_Int32 i_nItemPosition, const ::boost::optional< ::rtl::OUString >& i_rItemText,
    const ::boost::optional< ::rtl::OUString >& i_rItemImageURL,
    void ( SAL_CALL XItemListListener::*NotificationMethod )( const ItemListEvent& ) )
{
    ItemListEvent aEvent;
    aEvent.Source = *this;
    aEvent.ItemPosition = i_nItemPosition;
    if ( !!i_rItemText )
    {
        aEvent.ItemText.IsPresent = sal_True;
        aEvent.ItemText.Value = *i_rItemText;
    }
    if ( !!i_rItemImageURL )
    {
        aEvent.ItemImageURL.IsPresent = sal_True;
        aEvent.ItemImageURL.Value = *i_rItemImageURL;
    }

    m_aItemListListeners.notifyEach( NotificationMethod, aEvent );
}

//	----------------------------------------------------
//	class UnoListBoxControl
//	----------------------------------------------------
UnoListBoxControl::UnoListBoxControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoListBoxControl_Base( i_factory )
    ,maActionListeners( *this )
	,maItemListeners( *this )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
}

::rtl::OUString UnoListBoxControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "listbox" );
}
IMPL_SERVICEINFO_DERIVED( UnoListBoxControl, UnoControlBase, szServiceName2_UnoControlListBox )

void UnoListBoxControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maActionListeners.disposeAndClear( aEvt );
	maItemListeners.disposeAndClear( aEvt );
	UnoControl::dispose();
}

void UnoListBoxControl::ImplUpdateSelectedItemsProperty()
{
    if ( getPeer().is() )
    {
    	uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
    	DBG_ASSERT( xListBox.is(), "XListBox?" );

    	uno::Sequence<sal_Int16> aSeq = xListBox->getSelectedItemsPos();
    	uno::Any aAny;
    	aAny <<= aSeq;
    	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SELECTEDITEMS ), aAny, sal_False );
    }
}

void UnoListBoxControl::updateFromModel()
{
    UnoControlBase::updateFromModel();

    Reference< XItemListListener > xItemListListener( getPeer(), UNO_QUERY );
    ENSURE_OR_RETURN_VOID( xItemListListener.is(), "UnoListBoxControl::updateFromModel: a peer which is no ItemListListener?!" );

    EventObject aEvent( getModel() );
    xItemListListener->itemListChanged( aEvent );

    // notify the change of the SelectedItems property, again. While our base class, in updateFromModel,
    // already did this, our peer(s) can only legitimately set the selection after they have the string
    // item list, which we just notified with the itemListChanged call.
    const ::rtl::OUString sSelectedItemsPropName( GetPropertyName( BASEPROPERTY_SELECTEDITEMS ) );
    ImplSetPeerProperty( sSelectedItemsPropName, ImplGetPropertyValue( sSelectedItemsPropName ) );
}

void UnoListBoxControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const uno::Any& rVal )
{
    if ( rPropName == GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) )
        // do not forward this to our peer. We are a XItemListListener at our model, and changes in the string item
        // list (which is a legacy property) will, later, arrive as changes in the ItemList. Those latter changes
        // will be forwarded to the peer, which will update itself accordingly.
        return;

	UnoControl::ImplSetPeerProperty( rPropName, rVal );
}

void UnoListBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
	xListBox->addItemListener( this );

	if ( maActionListeners.getLength() )
		xListBox->addActionListener( &maActionListeners );
}

void UnoListBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	maActionListeners.addInterface( l );
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->addActionListener( &maActionListeners );
	}
}

void UnoListBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->removeActionListener( &maActionListeners );
	}
	maActionListeners.removeInterface( l );
}

void UnoListBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.addInterface( l );
}

void UnoListBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.removeInterface( l );
}

void UnoListBoxControl::addItem( const ::rtl::OUString& aItem, sal_Int16 nPos ) throw(uno::RuntimeException)
{
	uno::Sequence< ::rtl::OUString> aSeq( 1 );
	aSeq.getArray()[0] = aItem;
	addItems( aSeq, nPos );
}

void UnoListBoxControl::addItems( const uno::Sequence< ::rtl::OUString>& aItems, sal_Int16 nPos ) throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	sal_uInt16 nNewItems = (sal_uInt16)aItems.getLength();
	sal_uInt16 nOldLen = (sal_uInt16)aSeq.getLength();
	sal_uInt16 nNewLen = nOldLen + nNewItems;

	uno::Sequence< ::rtl::OUString> aNewSeq( nNewLen );
	::rtl::OUString* pNewData = aNewSeq.getArray();
	::rtl::OUString* pOldData = aSeq.getArray();

	if ( ( nPos < 0 ) || ( nPos > nOldLen ) )
		nPos = (sal_uInt16) nOldLen;

	sal_uInt16 n;
	// Items vor der Einfuege-Position
	for ( n = 0; n < nPos; n++ )
		pNewData[n] = pOldData[n];

	// Neue Items
	for ( n = 0; n < nNewItems; n++ )
		pNewData[nPos+n] = aItems.getConstArray()[n];

	// Rest der alten Items
	for ( n = nPos; n < nOldLen; n++ )
		pNewData[nNewItems+n] = pOldData[n];

	uno::Any aAny;
	aAny <<= aNewSeq;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), aAny, sal_True );
}

void UnoListBoxControl::removeItems( sal_Int16 nPos, sal_Int16 nCount ) throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	sal_uInt16 nOldLen = (sal_uInt16)aSeq.getLength();
	if ( nOldLen && ( nPos < nOldLen ) )
	{
		if ( nCount > ( nOldLen-nPos ) )
			nCount = nOldLen-nPos;

		sal_uInt16 nNewLen = nOldLen - nCount;

		uno::Sequence< ::rtl::OUString> aNewSeq( nNewLen );
		::rtl::OUString* pNewData = aNewSeq.getArray();
		::rtl::OUString* pOldData = aSeq.getArray();

		sal_uInt16 n;
		// Items vor der Entfern-Position
		for ( n = 0; n < nPos; n++ )
			pNewData[n] = pOldData[n];

		// Rest der Items
		for ( n = nPos; n < (nOldLen-nCount); n++ )
			pNewData[n] = pOldData[n+nCount];

		uno::Any aAny;
		aAny <<= aNewSeq;
		ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), aAny, sal_True );
	}
}

sal_Int16 UnoListBoxControl::getItemCount() throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	return (sal_Int16)aSeq.getLength();
}

::rtl::OUString UnoListBoxControl::getItem( sal_Int16 nPos ) throw(uno::RuntimeException)
{
	::rtl::OUString aItem;
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	if ( nPos < aSeq.getLength() )
		aItem = aSeq.getConstArray()[nPos];
	return aItem;
}

uno::Sequence< ::rtl::OUString> UnoListBoxControl::getItems() throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	return aSeq;
}

sal_Int16 UnoListBoxControl::getSelectedItemPos() throw(uno::RuntimeException)
{
	sal_Int16 n = -1;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		n = xListBox->getSelectedItemPos();
	}
	return n;
}

uno::Sequence<sal_Int16> UnoListBoxControl::getSelectedItemsPos() throw(uno::RuntimeException)
{
	uno::Sequence<sal_Int16> aSeq;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		aSeq = xListBox->getSelectedItemsPos();
	}
	return aSeq;
}

::rtl::OUString UnoListBoxControl::getSelectedItem() throw(uno::RuntimeException)
{
	::rtl::OUString aItem;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		aItem = xListBox->getSelectedItem();
	}
	return aItem;
}

uno::Sequence< ::rtl::OUString> UnoListBoxControl::getSelectedItems() throw(uno::RuntimeException)
{
	uno::Sequence< ::rtl::OUString> aSeq;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		aSeq = xListBox->getSelectedItems();
	}
	return aSeq;
}

void UnoListBoxControl::selectItemPos( sal_Int16 nPos, sal_Bool bSelect ) throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->selectItemPos( nPos, bSelect );
	}
	ImplUpdateSelectedItemsProperty();
}

void UnoListBoxControl::selectItemsPos( const uno::Sequence<sal_Int16>& aPositions, sal_Bool bSelect ) throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->selectItemsPos( aPositions, bSelect );
	}
	ImplUpdateSelectedItemsProperty();
}

void UnoListBoxControl::selectItem( const ::rtl::OUString& aItem, sal_Bool bSelect ) throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->selectItem( aItem, bSelect );
	}
	ImplUpdateSelectedItemsProperty();
}

void UnoListBoxControl::makeVisible( sal_Int16 nEntry ) throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XListBox >  xListBox( getPeer(), uno::UNO_QUERY );
		xListBox->makeVisible( nEntry );
	}
}

void UnoListBoxControl::setDropDownLineCount( sal_Int16 nLines ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= (sal_Int16)nLines;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINECOUNT ), aAny, sal_True );
}

sal_Int16 UnoListBoxControl::getDropDownLineCount() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT16( BASEPROPERTY_LINECOUNT );
}

sal_Bool UnoListBoxControl::isMutipleMode() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_MULTISELECTION );
}

void UnoListBoxControl::setMultipleMode( sal_Bool bMulti ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bMulti;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MULTISELECTION ), aAny, sal_True );
}

void UnoListBoxControl::itemStateChanged( const awt::ItemEvent& rEvent ) throw(uno::RuntimeException)
{
    ImplUpdateSelectedItemsProperty();
	if ( maItemListeners.getLength() )
    {
        try
        {
		    maItemListeners.itemStateChanged( rEvent );
        }
        catch( const Exception& e )
        {
#if OSL_DEBUG_LEVEL == 0
            (void) e; // suppress warning
#else
            ::rtl::OString sMessage( "UnoListBoxControl::itemStateChanged: caught an exception:\n" );
            sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US );
        	OSL_ENSURE( sal_False, sMessage.getStr() );
#endif
        }
    }
}

awt::Size UnoListBoxControl::getMinimumSize(  ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize();
}

awt::Size UnoListBoxControl::getPreferredSize(  ) throw(uno::RuntimeException)
{
	return Impl_getPreferredSize();
}

awt::Size UnoListBoxControl::calcAdjustedSize( const awt::Size& rNewSize ) throw(uno::RuntimeException)
{
	return Impl_calcAdjustedSize( rNewSize );
}

awt::Size UnoListBoxControl::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines ) throw(uno::RuntimeException)
{
	return Impl_getMinimumSize( nCols, nLines );
}

void UnoListBoxControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines ) throw(uno::RuntimeException)
{
	Impl_getColumnsAndLines( nCols, nLines );
}

sal_Bool SAL_CALL UnoListBoxControl::setModel( const uno::Reference< awt::XControlModel >& i_rModel ) throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( GetMutex() );

    const Reference< XItemList > xOldItems( getModel(), UNO_QUERY );
    OSL_ENSURE( xOldItems.is() || !getModel().is(), "UnoListBoxControl::setModel: illegal old model!" );
    const Reference< XItemList > xNewItems( i_rModel, UNO_QUERY );
    OSL_ENSURE( xNewItems.is() || !i_rModel.is(), "UnoListBoxControl::setModel: illegal new model!" );

    if ( !UnoListBoxControl_Base::setModel( i_rModel ) )
        return sal_False;

    if ( xOldItems.is() )
        xOldItems->removeItemListListener( this );
    if ( xNewItems.is() )
        xNewItems->addItemListListener( this );

    return sal_True;
}

void SAL_CALL UnoListBoxControl::listItemInserted( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemInserted: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemInserted( i_rEvent );
}

void SAL_CALL UnoListBoxControl::listItemRemoved( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemRemoved: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemRemoved( i_rEvent );
}

void SAL_CALL UnoListBoxControl::listItemModified( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemModified: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemModified( i_rEvent );
}

void SAL_CALL UnoListBoxControl::allItemsRemoved( const lang::EventObject& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::allItemsRemoved: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->allItemsRemoved( i_rEvent );
}

void SAL_CALL UnoListBoxControl::itemListChanged( const lang::EventObject& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::itemListChanged: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->itemListChanged( i_rEvent );
}
ActionListenerMultiplexer& 	UnoListBoxControl::getActionListeners()
{
    return maActionListeners;
}
ItemListenerMultiplexer& 	UnoListBoxControl::getItemListeners()
{
    return maItemListeners;
}
//	----------------------------------------------------
//	class UnoControlComboBoxModel
//	----------------------------------------------------
UnoControlComboBoxModel::UnoControlComboBoxModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlListBoxModel( i_factory, ConstructWithoutProperties )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXComboBox );
}

IMPL_SERVICEINFO_DERIVED( UnoControlComboBoxModel, UnoControlModel, szServiceName2_UnoControlComboBoxModel )

uno::Reference< beans::XPropertySetInfo > UnoControlComboBoxModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}
// ---------------------------------------------------------------------------------------------------------------------
::cppu::IPropertyArrayHelper& UnoControlComboBoxModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}


::rtl::OUString UnoControlComboBoxModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlComboBoxModel );
}
void SAL_CALL UnoControlComboBoxModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue ) throw (uno::Exception)
{
    UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );

    if ( nHandle == BASEPROPERTY_STRINGITEMLIST && !m_pData->m_bSettingLegacyProperty)
	{
        // synchronize the legacy StringItemList property with our list items
        Sequence< ::rtl::OUString > aStringItemList;
        Any aPropValue;
        getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
        OSL_VERIFY( aPropValue >>= aStringItemList );

        ::std::vector< ListItem > aItems( aStringItemList.getLength() );
        ::std::transform(
            aStringItemList.getConstArray(),
            aStringItemList.getConstArray() + aStringItemList.getLength(),
            aItems.begin(),
            CreateListItem()
        );
        m_pData->setAllItems( aItems );

        // since an XItemListListener does not have a "all items modified" or some such method,
        // we simulate this by notifying removal of all items, followed by insertion of all new
        // items
        lang::EventObject aEvent;
        aEvent.Source = *this;
        m_aItemListListeners.notifyEach( &XItemListListener::itemListChanged, aEvent );
        // TODO: OPropertySetHelper calls into this method with the mutex locked ...
        // which is wrong for the above notifications ...
	}
}

uno::Any UnoControlComboBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlComboBox );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

//	----------------------------------------------------
//	class UnoComboBoxControl
//	----------------------------------------------------
UnoComboBoxControl::UnoComboBoxControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoEditControl( i_factory )
	,maActionListeners( *this )
    ,maItemListeners( *this )
{
	maComponentInfos.nWidth = 100;
	maComponentInfos.nHeight = 12;
}
IMPL_SERVICEINFO_DERIVED( UnoComboBoxControl, UnoEditControl, szServiceName2_UnoControlComboBox )

::rtl::OUString UnoComboBoxControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "combobox" );
}

void UnoComboBoxControl::dispose() throw(uno::RuntimeException)
{
	lang::EventObject aEvt;
	aEvt.Source = (::cppu::OWeakObject*)this;
	maActionListeners.disposeAndClear( aEvt );
	maItemListeners.disposeAndClear( aEvt );
	UnoControl::dispose();
}
uno::Any UnoComboBoxControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XComboBox*, this ) );
    if ( !aRet.hasValue() )
    {
        aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XItemListener*, this ) );
        if ( !aRet.hasValue() )
        {
            aRet = ::cppu::queryInterface( rType,
										    SAL_STATIC_CAST( awt::XItemListListener*, this ) );
        }
    }
	return (aRet.hasValue() ? aRet : UnoEditControl::queryAggregation( rType ));
}
// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoComboBoxControl )
	getCppuType( ( uno::Reference< awt::XComboBox>* ) NULL ),
    getCppuType( ( uno::Reference< awt::XItemListener>* ) NULL ),
    getCppuType( ( uno::Reference< awt::XItemListListener>* ) NULL ),
	UnoEditControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoComboBoxControl::updateFromModel()
{
    UnoEditControl::updateFromModel();

    Reference< XItemListListener > xItemListListener( getPeer(), UNO_QUERY );
    ENSURE_OR_RETURN_VOID( xItemListListener.is(), "UnoComboBoxControl::updateFromModel: a peer which is no ItemListListener?!" );

    EventObject aEvent( getModel() );
    xItemListListener->itemListChanged( aEvent );
}
void UnoComboBoxControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const uno::Any& rVal )
{
    if ( rPropName == GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) )
        // do not forward this to our peer. We are a XItemListListener at our model, and changes in the string item
        // list (which is a legacy property) will, later, arrive as changes in the ItemList. Those latter changes
        // will be forwarded to the peer, which will update itself accordingly.
        return;

	UnoEditControl::ImplSetPeerProperty( rPropName, rVal );
}
void UnoComboBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoEditControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XComboBox >  xComboBox( getPeer(), uno::UNO_QUERY );
	if ( maActionListeners.getLength() )
		xComboBox->addActionListener( &maActionListeners );
	if ( maItemListeners.getLength() )
		xComboBox->addItemListener( &maItemListeners );
}

void UnoComboBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	maActionListeners.addInterface( l );
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XComboBox >  xComboBox( getPeer(), uno::UNO_QUERY );
		xComboBox->addActionListener( &maActionListeners );
	}
}

void UnoComboBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maActionListeners.getLength() == 1 )
	{
		uno::Reference < awt::XComboBox >  xComboBox( getPeer(), uno::UNO_QUERY );
		xComboBox->removeActionListener( &maActionListeners );
	}
	maActionListeners.removeInterface( l );
}

void UnoComboBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	maItemListeners.addInterface( l );
	if( getPeer().is() && maItemListeners.getLength() == 1 )
	{
		uno::Reference < awt::XComboBox >  xComboBox( getPeer(), uno::UNO_QUERY );
		xComboBox->addItemListener( &maItemListeners );
	}
}

void UnoComboBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l) throw(uno::RuntimeException)
{
	if( getPeer().is() && maItemListeners.getLength() == 1 )
	{
		uno::Reference < awt::XComboBox >  xComboBox( getPeer(), uno::UNO_QUERY );	// MT: Mal alles so umstellen, schoener als Ref anlegen und query rufen
		xComboBox->removeItemListener( &maItemListeners );
	}
	maItemListeners.removeInterface( l );
}
void UnoComboBoxControl::itemStateChanged( const awt::ItemEvent& rEvent ) throw(uno::RuntimeException)
{
	if ( maItemListeners.getLength() )
    {
        try
        {
		    maItemListeners.itemStateChanged( rEvent );
        }
        catch( const Exception& e )
        {
#if OSL_DEBUG_LEVEL == 0
            (void) e; // suppress warning
#else
            ::rtl::OString sMessage( "UnoComboBoxControl::itemStateChanged: caught an exception:\n" );
            sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US );
        	OSL_ENSURE( sal_False, sMessage.getStr() );
#endif
        }
    }
}
sal_Bool SAL_CALL UnoComboBoxControl::setModel( const uno::Reference< awt::XControlModel >& i_rModel ) throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( GetMutex() );

    const Reference< XItemList > xOldItems( getModel(), UNO_QUERY );
    OSL_ENSURE( xOldItems.is() || !getModel().is(), "UnoComboBoxControl::setModel: illegal old model!" );
    const Reference< XItemList > xNewItems( i_rModel, UNO_QUERY );
    OSL_ENSURE( xNewItems.is() || !i_rModel.is(), "UnoComboBoxControl::setModel: illegal new model!" );

    if ( !UnoEditControl::setModel( i_rModel ) )
        return sal_False;

    if ( xOldItems.is() )
        xOldItems->removeItemListListener( this );
    if ( xNewItems.is() )
        xNewItems->addItemListListener( this );

    return sal_True;
}

void SAL_CALL UnoComboBoxControl::listItemInserted( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemInserted: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemInserted( i_rEvent );
}

void SAL_CALL UnoComboBoxControl::listItemRemoved( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemRemoved: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemRemoved( i_rEvent );
}

void SAL_CALL UnoComboBoxControl::listItemModified( const awt::ItemListEvent& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemModified: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->listItemModified( i_rEvent );
}

void SAL_CALL UnoComboBoxControl::allItemsRemoved( const lang::EventObject& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::allItemsRemoved: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->allItemsRemoved( i_rEvent );
}

void SAL_CALL UnoComboBoxControl::itemListChanged( const lang::EventObject& i_rEvent ) throw (uno::RuntimeException)
{
    const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
    OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::itemListChanged: invalid peer!" );
    if ( xPeerListener.is() )
        xPeerListener->itemListChanged( i_rEvent );
}
ActionListenerMultiplexer& 	UnoComboBoxControl::getActionListeners()
{
    return maActionListeners;
}
ItemListenerMultiplexer& 	UnoComboBoxControl::getItemListeners()
{
    return maItemListeners;
}

void UnoComboBoxControl::addItem( const ::rtl::OUString& aItem, sal_Int16 nPos ) throw(uno::RuntimeException)
{
	uno::Sequence< ::rtl::OUString> aSeq( 1 );
	aSeq.getArray()[0] = aItem;
	addItems( aSeq, nPos );
}

void UnoComboBoxControl::addItems( const uno::Sequence< ::rtl::OUString>& aItems, sal_Int16 nPos ) throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	sal_uInt16 nNewItems = (sal_uInt16)aItems.getLength();
	sal_uInt16 nOldLen = (sal_uInt16)aSeq.getLength();
	sal_uInt16 nNewLen = nOldLen + nNewItems;

	uno::Sequence< ::rtl::OUString> aNewSeq( nNewLen );
	::rtl::OUString* pNewData = aNewSeq.getArray();
	const ::rtl::OUString* pOldData = aSeq.getConstArray();

	if ( ( nPos < 0 ) || ( nPos > nOldLen ) )
		nPos = (sal_uInt16) nOldLen;

	sal_uInt16 n;
	// Items vor der Einfuege-Position
	for ( n = 0; n < nPos; n++ )
		pNewData[n] = pOldData[n];

	// Neue Items
	for ( n = 0; n < nNewItems; n++ )
		pNewData[nPos+n] = aItems.getConstArray()[n];

	// Rest der alten Items
	for ( n = nPos; n < nOldLen; n++ )
		pNewData[nNewItems+n] = pOldData[n];

	uno::Any aAny;
	aAny <<= aNewSeq;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), aAny, sal_True );
}

void UnoComboBoxControl::removeItems( sal_Int16 nPos, sal_Int16 nCount ) throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	sal_uInt16 nOldLen = (sal_uInt16)aSeq.getLength();
	if ( nOldLen && ( nPos < nOldLen ) )
	{
		if ( nCount > ( nOldLen-nPos ) )
			nCount = nOldLen-nPos;

		sal_uInt16 nNewLen = nOldLen - nCount;

		uno::Sequence< ::rtl::OUString> aNewSeq( nNewLen );
		::rtl::OUString* pNewData = aNewSeq.getArray();
		::rtl::OUString* pOldData = aSeq.getArray();

		sal_uInt16 n;
		// Items vor der Entfern-Position
		for ( n = 0; n < nPos; n++ )
			pNewData[n] = pOldData[n];

		// Rest der Items
		for ( n = nPos; n < (nOldLen-nCount); n++ )
			pNewData[n] = pOldData[n+nCount];

		uno::Any aAny;
		aAny <<= aNewSeq;
		ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), aAny, sal_True );
	}
}

sal_Int16 UnoComboBoxControl::getItemCount() throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	return (sal_Int16)aSeq.getLength();
}

::rtl::OUString UnoComboBoxControl::getItem( sal_Int16 nPos ) throw(uno::RuntimeException)
{
	::rtl::OUString aItem;
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	if ( nPos < aSeq.getLength() )
		aItem = aSeq.getConstArray()[nPos];
	return aItem;
}

uno::Sequence< ::rtl::OUString> UnoComboBoxControl::getItems() throw(uno::RuntimeException)
{
	uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
	uno::Sequence< ::rtl::OUString> aSeq;
	aVal >>= aSeq;
	return aSeq;
}

void UnoComboBoxControl::setDropDownLineCount( sal_Int16 nLines ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= nLines;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINECOUNT ), aAny, sal_True );
}

sal_Int16 UnoComboBoxControl::getDropDownLineCount() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT16( BASEPROPERTY_LINECOUNT );
}


//	----------------------------------------------------
//	UnoSpinFieldControl
//	----------------------------------------------------
UnoSpinFieldControl::UnoSpinFieldControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoEditControl( i_factory )
    ,maSpinListeners( *this )
{
    mbRepeat = sal_False;
}

// uno::XInterface
uno::Any UnoSpinFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XSpinField*, this ) );
	return (aRet.hasValue() ? aRet : UnoEditControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoSpinFieldControl )
	getCppuType( ( uno::Reference< awt::XSpinField>* ) NULL ),
	UnoEditControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoSpinFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoEditControl::createPeer( rxToolkit, rParentPeer );

    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
    xField->enableRepeat( mbRepeat );
	if ( maSpinListeners.getLength() )
		xField->addSpinListener( &maSpinListeners );
}

	// ::com::sun::star::awt::XSpinField
void UnoSpinFieldControl::addSpinListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XSpinListener >& l ) throw(::com::sun::star::uno::RuntimeException)
{
	maSpinListeners.addInterface( l );
	if( getPeer().is() && maSpinListeners.getLength() == 1 )
	{
		uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
		xField->addSpinListener( &maSpinListeners );
	}
}

void UnoSpinFieldControl::removeSpinListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XSpinListener >& l ) throw(::com::sun::star::uno::RuntimeException)
{
	if( getPeer().is() && maSpinListeners.getLength() == 1 )
	{
		uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
		xField->removeSpinListener( &maSpinListeners );
	}
	maSpinListeners.removeInterface( l );
}

void UnoSpinFieldControl::up() throw(::com::sun::star::uno::RuntimeException)
{
    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
	if ( xField.is() )
        xField->up();
}

void UnoSpinFieldControl::down() throw(::com::sun::star::uno::RuntimeException)
{
    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
	if ( xField.is() )
        xField->down();
}

void UnoSpinFieldControl::first() throw(::com::sun::star::uno::RuntimeException)
{
    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
	if ( xField.is() )
        xField->first();
}

void UnoSpinFieldControl::last() throw(::com::sun::star::uno::RuntimeException)
{
    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
	if ( xField.is() )
        xField->last();
}

void UnoSpinFieldControl::enableRepeat( sal_Bool bRepeat ) throw(::com::sun::star::uno::RuntimeException)
{
    mbRepeat = bRepeat;

    uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
	if ( xField.is() )
        xField->enableRepeat( bRepeat );
}

//	----------------------------------------------------
//	class UnoControlDateFieldModel
//	----------------------------------------------------
UnoControlDateFieldModel::UnoControlDateFieldModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXDateField );
}

::rtl::OUString UnoControlDateFieldModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlDateFieldModel );
}

uno::Any UnoControlDateFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlDateField );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}


::cppu::IPropertyArrayHelper& UnoControlDateFieldModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlDateFieldModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}



//	----------------------------------------------------
//	class UnoDateFieldControl
//	----------------------------------------------------
UnoDateFieldControl::UnoDateFieldControl( const Reference< XMultiServiceFactory >& i_factory )
    :UnoSpinFieldControl( i_factory )
{
    mnFirst = Date( 1, 1, 1900 ).GetDate();
    mnLast = Date( 31, 12, 2200 ).GetDate();
    mbLongFormat = 2;
}

::rtl::OUString UnoDateFieldControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "datefield" );
}

// uno::XInterface
uno::Any UnoDateFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XDateField*, this ) );
	return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoDateFieldControl )
	getCppuType( ( uno::Reference< awt::XDateField>* ) NULL ),
	UnoSpinFieldControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoDateFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
	xField->setFirst( mnFirst );
    xField->setLast( mnLast );
    if ( mbLongFormat != 2 )    // not set
        xField->setLongFormat( mbLongFormat );
}


void UnoDateFieldControl::textChanged( const awt::TextEvent& e ) throw(uno::RuntimeException)
{
    uno::Reference< awt::XVclWindowPeer > xPeer( getPeer(), uno::UNO_QUERY );

    // also change the text property (#i25106#)
    if ( xPeer.is() )
    {
        ::rtl::OUString sTextPropertyName = GetPropertyName( BASEPROPERTY_TEXT );
        ImplSetPropertyValue( sTextPropertyName, xPeer->getProperty( sTextPropertyName ), sal_False );
    }

    // re-calc the Date property
    uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
	uno::Any aValue;
    if ( xField->isEmpty() )
    {
        // the field says it's empty
        sal_Bool bEnforceFormat = sal_True;
        if ( xPeer.is() )
            xPeer->getProperty( GetPropertyName( BASEPROPERTY_ENFORCE_FORMAT ) ) >>= bEnforceFormat;
        if ( !bEnforceFormat )
        {
            // and it also says that it is currently accepting invalid inputs, without
            // forcing it to a valid date
            uno::Reference< awt::XTextComponent > xText( xPeer, uno::UNO_QUERY );
            if ( xText.is() && xText->getText().getLength() )
                // and in real, the text of the peer is *not* empty
                // -> simulate an invalid date, which is different from "no date"
                aValue <<= util::Date( 0, 0, 0 );
        }
    }
    else
		aValue <<= xField->getDate();

	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATE ), aValue, sal_False );

    // multiplex the event
    if ( GetTextListeners().getLength() )
		GetTextListeners().textChanged( e );
}

void UnoDateFieldControl::setDate( sal_Int32 Date ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Date;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATE ), aAny, sal_True );
}

sal_Int32 UnoDateFieldControl::getDate() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_DATE );
}

void UnoDateFieldControl::setMin( sal_Int32 Date ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Date;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATEMIN ), aAny, sal_True );
}

sal_Int32 UnoDateFieldControl::getMin() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_DATEMIN );
}

void UnoDateFieldControl::setMax( sal_Int32 Date ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Date;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATEMAX ), aAny, sal_True );
}

sal_Int32 UnoDateFieldControl::getMax() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_DATEMAX );
}

void UnoDateFieldControl::setFirst( sal_Int32 Date ) throw(uno::RuntimeException)
{
	mnFirst = Date;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
        xField->setFirst( Date );
    }
}

sal_Int32 UnoDateFieldControl::getFirst() throw(uno::RuntimeException)
{
	return mnFirst;
}

void UnoDateFieldControl::setLast( sal_Int32 Date ) throw(uno::RuntimeException)
{
	mnLast = Date;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
        xField->setLast( Date );
    }
}

sal_Int32 UnoDateFieldControl::getLast() throw(uno::RuntimeException)
{
	return mnLast;
}

void UnoDateFieldControl::setLongFormat( sal_Bool bLong ) throw(uno::RuntimeException)
{
	mbLongFormat = bLong;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
        xField->setLongFormat( bLong );
    }
}

sal_Bool UnoDateFieldControl::isLongFormat() throw(uno::RuntimeException)
{
	return ( mbLongFormat != 2 ) ? mbLongFormat : sal_False;
}

void UnoDateFieldControl::setEmpty() throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XDateField >  xField( getPeer(), uno::UNO_QUERY );
		xField->setEmpty();
	}
}

sal_Bool UnoDateFieldControl::isEmpty() throw(uno::RuntimeException)
{
	sal_Bool bEmpty = sal_False;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
		bEmpty = xField->isEmpty();
	}
	return bEmpty;
}

void UnoDateFieldControl::setStrictFormat( sal_Bool bStrict ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bStrict;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), aAny, sal_True );
}

sal_Bool UnoDateFieldControl::isStrictFormat() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
}

//	----------------------------------------------------
//	class UnoControlTimeFieldModel
//	----------------------------------------------------
UnoControlTimeFieldModel::UnoControlTimeFieldModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXTimeField );
}

::rtl::OUString UnoControlTimeFieldModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlTimeFieldModel );
}

uno::Any UnoControlTimeFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlTimeField );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}


::cppu::IPropertyArrayHelper& UnoControlTimeFieldModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlTimeFieldModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}



//	----------------------------------------------------
//	class UnoTimeFieldControl
//	----------------------------------------------------
UnoTimeFieldControl::UnoTimeFieldControl( const Reference< XMultiServiceFactory >& i_factory )
    :UnoSpinFieldControl( i_factory )
{
    mnFirst = Time( 0, 0 ).GetTime();
    mnLast = Time( 23, 59, 59, 99 ).GetTime();
}

::rtl::OUString UnoTimeFieldControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "timefield" );
}

// uno::XInterface
uno::Any UnoTimeFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XTimeField*, this ) );
	return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoTimeFieldControl )
	getCppuType( ( uno::Reference< awt::XTimeField>* ) NULL ),
	UnoSpinFieldControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoTimeFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
	xField->setFirst( mnFirst );
    xField->setLast( mnLast );
}

void UnoTimeFieldControl::textChanged( const awt::TextEvent& e ) throw(uno::RuntimeException)
{
    // also change the text property (#i25106#)
    uno::Reference< awt::XVclWindowPeer > xPeer( getPeer(), uno::UNO_QUERY );
    ::rtl::OUString sTextPropertyName = GetPropertyName( BASEPROPERTY_TEXT );
    ImplSetPropertyValue( sTextPropertyName, xPeer->getProperty( sTextPropertyName ), sal_False );

    // re-calc the Time property
	uno::Reference < awt::XTimeField >  xField( getPeer(), uno::UNO_QUERY );
	uno::Any aValue;
	if ( !xField->isEmpty() )
		aValue <<= xField->getTime();
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIME ), aValue, sal_False );

    // multiplex the event
    if ( GetTextListeners().getLength() )
		GetTextListeners().textChanged( e );
}

void UnoTimeFieldControl::setTime( sal_Int32 Time ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Time;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIME ), aAny, sal_True );
}

sal_Int32 UnoTimeFieldControl::getTime() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_TIME );
}

void UnoTimeFieldControl::setMin( sal_Int32 Time ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Time;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIMEMIN ), aAny, sal_True );
}

sal_Int32 UnoTimeFieldControl::getMin() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_TIMEMIN );
}

void UnoTimeFieldControl::setMax( sal_Int32 Time ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Time;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIMEMAX ), aAny, sal_True );
}

sal_Int32 UnoTimeFieldControl::getMax() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_TIMEMAX );
}

void UnoTimeFieldControl::setFirst( sal_Int32 Time ) throw(uno::RuntimeException)
{
	mnFirst = Time;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
        xField->setFirst( mnFirst );
    }
}

sal_Int32 UnoTimeFieldControl::getFirst() throw(uno::RuntimeException)
{
	return mnFirst;
}

void UnoTimeFieldControl::setLast( sal_Int32 Time ) throw(uno::RuntimeException)
{
	mnLast = Time;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
        xField->setFirst( mnLast );
    }
}

sal_Int32 UnoTimeFieldControl::getLast() throw(uno::RuntimeException)
{
	return mnLast;
}

void UnoTimeFieldControl::setEmpty() throw(uno::RuntimeException)
{
	if ( getPeer().is() )
	{
		uno::Reference < awt::XTimeField >  xField( getPeer(), uno::UNO_QUERY );
		xField->setEmpty();
	}
}

sal_Bool UnoTimeFieldControl::isEmpty() throw(uno::RuntimeException)
{
	sal_Bool bEmpty = sal_False;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XTimeField >  xField( getPeer(), uno::UNO_QUERY );
		bEmpty = xField->isEmpty();
	}
	return bEmpty;
}

void UnoTimeFieldControl::setStrictFormat( sal_Bool bStrict ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bStrict;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), aAny, sal_True );
}

sal_Bool UnoTimeFieldControl::isStrictFormat() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
}

//	----------------------------------------------------
//	class UnoControlNumericFieldModel
//	----------------------------------------------------
UnoControlNumericFieldModel::UnoControlNumericFieldModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXNumericField );
}

::rtl::OUString UnoControlNumericFieldModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlNumericFieldModel );
}

uno::Any UnoControlNumericFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlNumericField );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}


::cppu::IPropertyArrayHelper& UnoControlNumericFieldModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlNumericFieldModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}



//	----------------------------------------------------
//	class UnoNumericFieldControl
//	----------------------------------------------------
UnoNumericFieldControl::UnoNumericFieldControl( const Reference< XMultiServiceFactory >& i_factory )
    :UnoSpinFieldControl( i_factory )
{
    mnFirst = 0;
    mnLast = 0x7FFFFFFF;
}

::rtl::OUString UnoNumericFieldControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "numericfield" );
}

// uno::XInterface
uno::Any UnoNumericFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XNumericField*, this ) );
	return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoNumericFieldControl )
	getCppuType( ( uno::Reference< awt::XNumericField>* ) NULL ),
	UnoSpinFieldControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoNumericFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
	xField->setFirst( mnFirst );
    xField->setLast( mnLast );
}


void UnoNumericFieldControl::textChanged( const awt::TextEvent& e ) throw(uno::RuntimeException)
{
	uno::Reference < awt::XNumericField >  xField( getPeer(), uno::UNO_QUERY );
	uno::Any aAny;
	aAny <<= xField->getValue();
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), aAny, sal_False );

	if ( GetTextListeners().getLength() )
		GetTextListeners().textChanged( e );
}

void UnoNumericFieldControl::setValue( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), aAny, sal_True );
}

double UnoNumericFieldControl::getValue() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUE_DOUBLE );
}

void UnoNumericFieldControl::setMin( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMIN_DOUBLE ), aAny, sal_True );
}

double UnoNumericFieldControl::getMin() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMIN_DOUBLE );
}

void UnoNumericFieldControl::setMax( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMAX_DOUBLE ), aAny, sal_True );
}

double UnoNumericFieldControl::getMax() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMAX_DOUBLE );
}

void UnoNumericFieldControl::setFirst( double Value ) throw(uno::RuntimeException)
{
	mnFirst = Value;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
        xField->setFirst( mnFirst );
    }
}

double UnoNumericFieldControl::getFirst() throw(uno::RuntimeException)
{
	return mnFirst;
}

void UnoNumericFieldControl::setLast( double Value ) throw(uno::RuntimeException)
{
	mnLast = Value;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
        xField->setLast( mnLast );
    }
}

double UnoNumericFieldControl::getLast() throw(uno::RuntimeException)
{
	return mnLast;
}

void UnoNumericFieldControl::setStrictFormat( sal_Bool bStrict ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bStrict;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), aAny, sal_True );
}

sal_Bool UnoNumericFieldControl::isStrictFormat() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
}

void UnoNumericFieldControl::setSpinSize( double Digits ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Digits;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUESTEP_DOUBLE ), aAny, sal_True );
}

double UnoNumericFieldControl::getSpinSize() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUESTEP_DOUBLE );
}

void UnoNumericFieldControl::setDecimalDigits( sal_Int16 Digits ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Digits;
    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DECIMALACCURACY ), aAny, sal_True );
}

sal_Int16 UnoNumericFieldControl::getDecimalDigits() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT16( BASEPROPERTY_DECIMALACCURACY );
}

//	----------------------------------------------------
//	class UnoControlCurrencyFieldModel
//	----------------------------------------------------
UnoControlCurrencyFieldModel::UnoControlCurrencyFieldModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXCurrencyField );
}

::rtl::OUString UnoControlCurrencyFieldModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlCurrencyFieldModel );
}

uno::Any UnoControlCurrencyFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlCurrencyField );
		return aAny;
	}
	if ( nPropId == BASEPROPERTY_CURSYM_POSITION )
	{
		uno::Any aAny;
		aAny <<= (sal_Bool)sal_False;
		return aAny;
	}

	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlCurrencyFieldModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlCurrencyFieldModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//	class UnoCurrencyFieldControl
//	----------------------------------------------------
UnoCurrencyFieldControl::UnoCurrencyFieldControl( const Reference< XMultiServiceFactory >& i_factory )
    :UnoSpinFieldControl( i_factory )
{
    mnFirst = 0;
    mnLast = 0x7FFFFFFF;
}

::rtl::OUString UnoCurrencyFieldControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "longcurrencyfield" );
}

// uno::XInterface
uno::Any UnoCurrencyFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XCurrencyField*, this ) );
	return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoCurrencyFieldControl )
	getCppuType( ( uno::Reference< awt::XCurrencyField>* ) NULL ),
	UnoSpinFieldControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoCurrencyFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
{
	UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );

	uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
	xField->setFirst( mnFirst );
    xField->setLast( mnLast );
}

void UnoCurrencyFieldControl::textChanged( const awt::TextEvent& e ) throw(uno::RuntimeException)
{
	uno::Reference < awt::XCurrencyField >  xField( getPeer(), uno::UNO_QUERY );
	uno::Any aAny;
	aAny <<= xField->getValue();
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), aAny, sal_False );

	if ( GetTextListeners().getLength() )
		GetTextListeners().textChanged( e );
}

void UnoCurrencyFieldControl::setValue( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), aAny, sal_True );
}

double UnoCurrencyFieldControl::getValue() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUE_DOUBLE );
}

void UnoCurrencyFieldControl::setMin( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMIN_DOUBLE ), aAny, sal_True );
}

double UnoCurrencyFieldControl::getMin() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMIN_DOUBLE );
}

void UnoCurrencyFieldControl::setMax( double Value ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Value;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMAX_DOUBLE ), aAny, sal_True );
}

double UnoCurrencyFieldControl::getMax() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMAX_DOUBLE );
}

void UnoCurrencyFieldControl::setFirst( double Value ) throw(uno::RuntimeException)
{
	mnFirst = Value;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
        xField->setFirst( mnFirst );
    }
}

double UnoCurrencyFieldControl::getFirst() throw(uno::RuntimeException)
{
	return mnFirst;
}

void UnoCurrencyFieldControl::setLast( double Value ) throw(uno::RuntimeException)
{
	mnLast = Value;
	if ( getPeer().is() )
	{
		uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
        xField->setLast( mnLast );
    }
}

double UnoCurrencyFieldControl::getLast() throw(uno::RuntimeException)
{
	return mnLast;
}

void UnoCurrencyFieldControl::setStrictFormat( sal_Bool bStrict ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bStrict;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), aAny, sal_True );
}

sal_Bool UnoCurrencyFieldControl::isStrictFormat() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
}

void UnoCurrencyFieldControl::setSpinSize( double Digits ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Digits;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUESTEP_DOUBLE ), aAny, sal_True );
}

double UnoCurrencyFieldControl::getSpinSize() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUESTEP_DOUBLE );
}

void UnoCurrencyFieldControl::setDecimalDigits( sal_Int16 Digits ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= Digits;
    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DECIMALACCURACY ), aAny, sal_True );
}

sal_Int16 UnoCurrencyFieldControl::getDecimalDigits() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_INT16( BASEPROPERTY_DECIMALACCURACY );
}

//	----------------------------------------------------
//	class UnoControlPatternFieldModel
//	----------------------------------------------------
UnoControlPatternFieldModel::UnoControlPatternFieldModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
    UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXPatternField );
}

::rtl::OUString UnoControlPatternFieldModel::getServiceName() throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlPatternFieldModel );
}

uno::Any UnoControlPatternFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlPatternField );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlPatternFieldModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlPatternFieldModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}


//	----------------------------------------------------
//	class UnoPatternFieldControl
//	----------------------------------------------------
UnoPatternFieldControl::UnoPatternFieldControl( const Reference< XMultiServiceFactory >& i_factory )
    :UnoSpinFieldControl( i_factory )
{
}

::rtl::OUString UnoPatternFieldControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "patternfield" );
}

void UnoPatternFieldControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const uno::Any& rVal )
{
	sal_uInt16 nType = GetPropertyId( rPropName );
	if ( ( nType == BASEPROPERTY_TEXT ) || ( nType == BASEPROPERTY_EDITMASK ) || ( nType == BASEPROPERTY_LITERALMASK ) )
	{
		// Die Masken koennen nicht nacheinander gesetzt werden.
		::rtl::OUString Text = ImplGetPropertyValue_UString( BASEPROPERTY_TEXT );
		::rtl::OUString EditMask = ImplGetPropertyValue_UString( BASEPROPERTY_EDITMASK );
		::rtl::OUString LiteralMask = ImplGetPropertyValue_UString( BASEPROPERTY_LITERALMASK );

		uno::Reference < awt::XPatternField >  xPF( getPeer(), uno::UNO_QUERY );
		if (xPF.is())
		{
            // same comment as in UnoControl::ImplSetPeerProperty - see there
            ::rtl::OUString sText( Text );
            ImplCheckLocalize( sText );
			xPF->setString( sText );
			xPF->setMasks( EditMask, LiteralMask );
		}
	}
	else
		UnoSpinFieldControl::ImplSetPeerProperty( rPropName, rVal );
}


// uno::XInterface
uno::Any UnoPatternFieldControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XPatternField*, this ) );
	return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoPatternFieldControl )
	getCppuType( ( uno::Reference< awt::XPatternField>* ) NULL ),
	UnoSpinFieldControl::getTypes()
IMPL_XTYPEPROVIDER_END

void UnoPatternFieldControl::setString( const ::rtl::OUString& rString ) throw(uno::RuntimeException)
{
	setText( rString );
}

::rtl::OUString UnoPatternFieldControl::getString() throw(uno::RuntimeException)
{
	return getText();
}

void UnoPatternFieldControl::setMasks( const ::rtl::OUString& EditMask, const ::rtl::OUString& LiteralMask ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= EditMask;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_EDITMASK ), aAny, sal_True );
	aAny <<= LiteralMask;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LITERALMASK ), aAny, sal_True );
}

void UnoPatternFieldControl::getMasks( ::rtl::OUString& EditMask, ::rtl::OUString& LiteralMask ) throw(uno::RuntimeException)
{
	EditMask = ImplGetPropertyValue_UString( BASEPROPERTY_EDITMASK );
	LiteralMask = ImplGetPropertyValue_UString( BASEPROPERTY_LITERALMASK );
}

void UnoPatternFieldControl::setStrictFormat( sal_Bool bStrict ) throw(uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= bStrict;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), aAny, sal_True );
}

sal_Bool UnoPatternFieldControl::isStrictFormat() throw(uno::RuntimeException)
{
	return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
}


//	----------------------------------------------------
//	class UnoControlProgressBarModel
//	----------------------------------------------------
UnoControlProgressBarModel::UnoControlProgressBarModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
	ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
    ImplRegisterProperty( BASEPROPERTY_BORDER );
	ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
    ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
	ImplRegisterProperty( BASEPROPERTY_ENABLED );
	ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
	ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
    ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
	ImplRegisterProperty( BASEPROPERTY_HELPURL );
    ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
    ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE );
    ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE_MAX );
    ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE_MIN );
}

::rtl::OUString UnoControlProgressBarModel::getServiceName( ) throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlProgressBarModel );
}

uno::Any UnoControlProgressBarModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlProgressBar );
		return aAny;
	}

	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlProgressBarModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlProgressBarModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}


//	----------------------------------------------------
//	class UnoProgressBarControl
//	----------------------------------------------------
UnoProgressBarControl::UnoProgressBarControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
{
}

::rtl::OUString UnoProgressBarControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "ProgressBar" );
}

// uno::XInterface
uno::Any UnoProgressBarControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
{
	uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( awt::XProgressBar*, this ) );
	return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
}

// lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( UnoProgressBarControl )
	getCppuType( ( uno::Reference< awt::XProgressBar>* ) NULL ),
	UnoControlBase::getTypes()
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XProgressBar
void UnoProgressBarControl::setForegroundColor( sal_Int32 nColor ) throw(::com::sun::star::uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= nColor;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_FILLCOLOR ), aAny, sal_True );
}

void UnoProgressBarControl::setBackgroundColor( sal_Int32 nColor ) throw(::com::sun::star::uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= nColor;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_BACKGROUNDCOLOR ), aAny, sal_True );
}

void UnoProgressBarControl::setValue( sal_Int32 nValue ) throw(::com::sun::star::uno::RuntimeException)
{
	uno::Any aAny;
	aAny <<= nValue;
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE ), aAny, sal_True );
}

void UnoProgressBarControl::setRange( sal_Int32 nMin, sal_Int32 nMax ) throw(::com::sun::star::uno::RuntimeException )
{
	uno::Any aMin;
	uno::Any aMax;

	if ( nMin < nMax )
	{
		// take correct min and max
		aMin <<= nMin;
		aMax <<= nMax;
	}
	else
	{
		// change min and max
		aMin <<= nMax;
		aMax <<= nMin;
	}

	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE_MIN ), aMin, sal_True );
	ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE_MAX ), aMax, sal_True );
}

sal_Int32 UnoProgressBarControl::getValue() throw(::com::sun::star::uno::RuntimeException)
{
	return ImplGetPropertyValue_INT32( BASEPROPERTY_PROGRESSVALUE );
}


//	----------------------------------------------------
//	class UnoControlFixedLineModel
//	----------------------------------------------------
UnoControlFixedLineModel::UnoControlFixedLineModel( const Reference< XMultiServiceFactory >& i_factory )
    :UnoControlModel( i_factory )
{
	ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
	ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
	ImplRegisterProperty( BASEPROPERTY_ENABLED );
	ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
	ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
	ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
	ImplRegisterProperty( BASEPROPERTY_HELPURL );
	ImplRegisterProperty( BASEPROPERTY_LABEL );
    ImplRegisterProperty( BASEPROPERTY_ORIENTATION );
	ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
}

::rtl::OUString UnoControlFixedLineModel::getServiceName( ) throw(::com::sun::star::uno::RuntimeException)
{
	return ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedLineModel );
}

uno::Any UnoControlFixedLineModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
{
	if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
	{
		uno::Any aAny;
		aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlFixedLine );
		return aAny;
	}
	return UnoControlModel::ImplGetDefaultValue( nPropId );
}

::cppu::IPropertyArrayHelper& UnoControlFixedLineModel::getInfoHelper()
{
	static UnoPropertyArrayHelper* pHelper = NULL;
	if ( !pHelper )
	{
		uno::Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
		pHelper = new UnoPropertyArrayHelper( aIDs );
	}
	return *pHelper;
}

// beans::XMultiPropertySet
uno::Reference< beans::XPropertySetInfo > UnoControlFixedLineModel::getPropertySetInfo(  ) throw(uno::RuntimeException)
{
	static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
	return xInfo;
}

//	----------------------------------------------------
//	class UnoFixedLineControl
//	----------------------------------------------------
UnoFixedLineControl::UnoFixedLineControl( const Reference< XMultiServiceFactory >& i_factory )
	:UnoControlBase( i_factory )
{
	maComponentInfos.nWidth = 100;		// ??
	maComponentInfos.nHeight = 100;		// ??
}

::rtl::OUString UnoFixedLineControl::GetComponentServiceName()
{
	return ::rtl::OUString::createFromAscii( "FixedLine" );
}

sal_Bool UnoFixedLineControl::isTransparent() throw(uno::RuntimeException)
{
	return sal_True;
}

