/**************************************************************
 * 
 * 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_svtools.hxx"

#define _SVT_UNOIFACE_CXX
#include <tools/debug.hxx>
#include <vcl/svapp.hxx>
#include <svtools/svmedit.hxx>
#include <unoiface.hxx>
#include <svtools/filedlg.hxx>
#include <svtools/filectrl.hxx>
#include <svtools/roadmap.hxx>
#include <svtools/fixedhyper.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/awt/LineEndFormat.hpp>
#include <comphelper/processfactory.hxx>
#include <toolkit/helper/convert.hxx>
#include <toolkit/helper/property.hxx>
#include <svtools/fmtfield.hxx>
#include <svl/numuno.hxx>
#include <svtools/calendar.hxx>
#include <svtools/prgsbar.hxx>
#include <svtools/svtreebx.hxx>
#include "treecontrolpeer.hxx"
#include "svtxgridcontrol.hxx"
#include <svtools/table/tablecontrol.hxx>

namespace
{
    static void lcl_setWinBits( Window* _pWindow, WinBits _nBits, sal_Bool _bSet )
    {
        WinBits nStyle = _pWindow->GetStyle();
        if ( _bSet )
            nStyle |= _nBits;
        else
            nStyle &= ~_nBits;
        _pWindow->SetStyle( nStyle );
    }
}

//	----------------------------------------------------
//	help function for the toolkit...
//	----------------------------------------------------

extern "C" {

SAL_DLLPUBLIC_EXPORT Window* CreateWindow( VCLXWindow** ppNewComp, const ::com::sun::star::awt::WindowDescriptor* pDescriptor, Window* pParent, WinBits nWinBits )
{
	Window* pWindow = NULL;
	String aServiceName( pDescriptor->WindowServiceName );
	if ( aServiceName.EqualsIgnoreCaseAscii( "MultiLineEdit" ) )
	{
		if ( pParent )
		{
			pWindow = new MultiLineEdit( pParent, nWinBits|WB_IGNORETAB);
            static_cast< MultiLineEdit* >( pWindow )->DisableSelectionOnFocus();
			*ppNewComp = new VCLXMultiLineEdit;
		}
		else
		{
			*ppNewComp = NULL;
			return NULL;
		}
	}
	else if ( aServiceName.EqualsIgnoreCaseAscii( "FileControl" ) )
	{
		if ( pParent )
		{
			pWindow = new FileControl( pParent, nWinBits );
			*ppNewComp = new VCLXFileControl;
		}
		else
		{
			*ppNewComp = NULL;
			return NULL;
		}
	}
	else if (aServiceName.EqualsIgnoreCaseAscii("FormattedField") )
	{
		pWindow = new FormattedField( pParent, nWinBits );
		*ppNewComp = new SVTXFormattedField;
	}
	else if (aServiceName.EqualsIgnoreCaseAscii("NumericField") )
	{
		pWindow = new DoubleNumericField( pParent, nWinBits );
		*ppNewComp = new SVTXNumericField;
	}
	else if (aServiceName.EqualsIgnoreCaseAscii("LongCurrencyField") )
	{
		pWindow = new DoubleCurrencyField( pParent, nWinBits );
		*ppNewComp = new SVTXCurrencyField;
	}
	else if (aServiceName.EqualsIgnoreCaseAscii("datefield") )
	{
		pWindow = new CalendarField( pParent, nWinBits);
		static_cast<CalendarField*>(pWindow)->EnableToday();
		static_cast<CalendarField*>(pWindow)->EnableNone();
		static_cast<CalendarField*>(pWindow)->EnableEmptyFieldValue( sal_True );
		*ppNewComp = new SVTXDateField;
		((VCLXFormattedSpinField*)*ppNewComp)->SetFormatter( (FormatterBase*)(DateField*)pWindow );
	}
	else if (aServiceName.EqualsIgnoreCaseAscii("roadmap") )
	{
        pWindow = new ::svt::ORoadmap( pParent, WB_TABSTOP );
		*ppNewComp = new SVTXRoadmap;
	}
    else if ( aServiceName.EqualsIgnoreCaseAscii( "ProgressBar" ) )
	{
		if ( pParent )
		{
			pWindow = new ProgressBar( pParent, nWinBits );
			*ppNewComp = new VCLXProgressBar;
		}
		else
		{
			*ppNewComp = NULL;
			return NULL;
		}
	}
	else if ( aServiceName.EqualsIgnoreCaseAscii( "Tree" ) )
	{
		TreeControlPeer* pPeer = new TreeControlPeer;
		*ppNewComp = pPeer;
		pWindow = pPeer->createVclControl( pParent, nWinBits );
	}
    else if ( aServiceName.EqualsIgnoreCaseAscii( "FixedHyperlink" ) )
    {
        if ( pParent )
        {
            pWindow = new ::svt::FixedHyperlink( pParent, nWinBits );
            *ppNewComp = new VCLXFixedHyperlink;
        }
        else
        {
            *ppNewComp = NULL;
            return NULL;
        }
    }
	else if ( aServiceName.EqualsIgnoreCaseAscii( "Grid" ) )
	{
		if ( pParent )
		{	
			pWindow = new ::svt::table::TableControl(pParent, nWinBits);
			*ppNewComp = new SVTXGridControl;
		}
		else
		{
			*ppNewComp = NULL;
			return NULL;
		}
	}
	return pWindow;
}

}	// extern "C"

//	----------------------------------------------------
//	class VCLXMultiLineEdit
//	----------------------------------------------------
VCLXMultiLineEdit::VCLXMultiLineEdit()
    :maTextListeners( *this )
    ,meLineEndType( LINEEND_LF )    // default behavior before introducing this property: LF (unix-like)
{
}

VCLXMultiLineEdit::~VCLXMultiLineEdit()
{
}

::com::sun::star::uno::Any VCLXMultiLineEdit::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( ::com::sun::star::awt::XTextComponent*, this ),
										SAL_STATIC_CAST( ::com::sun::star::awt::XTextArea*, this ),
										SAL_STATIC_CAST( ::com::sun::star::awt::XTextLayoutConstrains*, this ),
										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
	return (aRet.hasValue() ? aRet : VCLXWindow::queryInterface( rType ));
}

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXMultiLineEdit )
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent>* ) NULL ),
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextArea>* ) NULL ),
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextLayoutConstrains>* ) NULL ),
	VCLXWindow::getTypes()
IMPL_XTYPEPROVIDER_END

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

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

void VCLXMultiLineEdit::setText( const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pEdit = (MultiLineEdit*)GetWindow();
	if ( pEdit )
	{
		pEdit->SetText( aText );

        // #107218# Call same listeners like VCL would do after user interaction
        SetSynthesizingVCLEvent( sal_True );
        pEdit->SetModifyFlag();
        pEdit->Modify();
        SetSynthesizingVCLEvent( sal_False );
	}
}

void VCLXMultiLineEdit::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pEdit = (MultiLineEdit*)GetWindow();
	if ( pEdit )
	{
		setSelection( rSel );
		pEdit->ReplaceSelected( aText );
	}
}

::rtl::OUString VCLXMultiLineEdit::getText() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::rtl::OUString aText;
	MultiLineEdit* pEdit = (MultiLineEdit*)GetWindow();
	if ( pEdit )
		aText = pEdit->GetText( meLineEndType );
	return aText;
}

::rtl::OUString VCLXMultiLineEdit::getSelectedText() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::rtl::OUString aText;
	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	if ( pMultiLineEdit)
		aText = pMultiLineEdit->GetSelected( meLineEndType );
	return aText;

}

void VCLXMultiLineEdit::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	if ( pMultiLineEdit )
	{
		pMultiLineEdit->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
	}
}

::com::sun::star::awt::Selection VCLXMultiLineEdit::getSelection() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Selection aSel;
	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	if ( pMultiLineEdit )
	{
		aSel.Min = pMultiLineEdit->GetSelection().Min();
		aSel.Max = pMultiLineEdit->GetSelection().Max();
	}
	return aSel;
}

sal_Bool VCLXMultiLineEdit::isEditable() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	return ( pMultiLineEdit && !pMultiLineEdit->IsReadOnly() && pMultiLineEdit->IsEnabled() ) ? sal_True : sal_False;
}

void VCLXMultiLineEdit::setEditable( sal_Bool bEditable ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	if ( pMultiLineEdit )
		pMultiLineEdit->SetReadOnly( !bEditable );
}

void VCLXMultiLineEdit::setMaxTextLen( sal_Int16 nLen ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	if ( pMultiLineEdit )
		pMultiLineEdit->SetMaxTextLen( nLen );
}

sal_Int16 VCLXMultiLineEdit::getMaxTextLen() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*) GetWindow();
	return pMultiLineEdit ? (sal_Int16)pMultiLineEdit->GetMaxTextLen() : (sal_Int16)0;
}

::rtl::OUString VCLXMultiLineEdit::getTextLines() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::rtl::OUString aText;
	MultiLineEdit* pEdit = (MultiLineEdit*)GetWindow();
	if ( pEdit )
		aText = pEdit->GetTextLines( meLineEndType );
	return aText;
}

::com::sun::star::awt::Size VCLXMultiLineEdit::getMinimumSize() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz;
	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
	if ( pEdit )
		aSz = AWTSize(pEdit->CalcMinimumSize());
	return aSz;
}

::com::sun::star::awt::Size VCLXMultiLineEdit::getPreferredSize() throw(::com::sun::star::uno::RuntimeException)
{
	return getMinimumSize();
}

::com::sun::star::awt::Size VCLXMultiLineEdit::calcAdjustedSize( const ::com::sun::star::awt::Size& rNewSize ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz = rNewSize;
	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
	if ( pEdit )
		aSz = AWTSize(pEdit->CalcAdjustedSize( VCLSize(rNewSize )));
	return aSz;
}

::com::sun::star::awt::Size VCLXMultiLineEdit::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz;
	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
	if ( pEdit )
		aSz = AWTSize(pEdit->CalcSize( nCols, nLines ));
	return aSz;
}

void VCLXMultiLineEdit::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	nCols = nLines = 0;
	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
	if ( pEdit )
	{
		sal_uInt16 nC, nL;
		pEdit->GetMaxVisColumnsAndLines( nC, nL );
		nCols = nC;
		nLines = nL;
	}
}

void VCLXMultiLineEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
{
	switch ( rVclWindowEvent.GetId() )
	{
		case VCLEVENT_EDIT_MODIFY:
        {
		    if ( maTextListeners.getLength() )
		    {
	            ::com::sun::star::awt::TextEvent aEvent;
	            aEvent.Source = (::cppu::OWeakObject*)this;
	            maTextListeners.textChanged( aEvent );
		    }
        }
        break;
		default:
        {
			VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
        }
		break;
	}
}

void VCLXMultiLineEdit::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*)GetWindow();
	if ( pMultiLineEdit )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch ( nPropType )
		{
            case BASEPROPERTY_LINE_END_FORMAT:
            {
                sal_Int16 nLineEndType = ::com::sun::star::awt::LineEndFormat::LINE_FEED;
                OSL_VERIFY( Value >>= nLineEndType );
                switch ( nLineEndType )
                {
                case ::com::sun::star::awt::LineEndFormat::CARRIAGE_RETURN:           meLineEndType = LINEEND_CR; break;
                case ::com::sun::star::awt::LineEndFormat::LINE_FEED:                 meLineEndType = LINEEND_LF; break;
                case ::com::sun::star::awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: meLineEndType = LINEEND_CRLF; break;
                default: DBG_ERROR( "VCLXMultiLineEdit::setProperty: invalid line end value!" ); break;
                }
            }
            break;

			case BASEPROPERTY_READONLY:
			{
				sal_Bool b = sal_Bool();
				if ( Value >>= b )
					pMultiLineEdit->SetReadOnly( b );
			}
			break;
			case BASEPROPERTY_MAXTEXTLEN:
			{
				sal_Int16 n = sal_Int16();
				if ( Value >>= n )
					pMultiLineEdit->SetMaxTextLen( n );
			}
			break;
			case BASEPROPERTY_HIDEINACTIVESELECTION:
			{
				sal_Bool b = sal_Bool();
				if ( Value >>= b )
                {
					pMultiLineEdit->EnableFocusSelectionHide( b );
                    lcl_setWinBits( pMultiLineEdit, WB_NOHIDESELECTION, !b );
                }
			}
			break;
			default:
			{
				VCLXWindow::setProperty( PropertyName, Value );
			}
		}
	}
}

::com::sun::star::uno::Any VCLXMultiLineEdit::getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aProp;
	MultiLineEdit* pMultiLineEdit = (MultiLineEdit*)GetWindow();
	if ( pMultiLineEdit )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch ( nPropType )
		{
            case BASEPROPERTY_LINE_END_FORMAT:
            {
                sal_Int16 nLineEndType = ::com::sun::star::awt::LineEndFormat::LINE_FEED;
                switch ( meLineEndType )
                {
                case LINEEND_CR:   nLineEndType = ::com::sun::star::awt::LineEndFormat::CARRIAGE_RETURN; break;
                case LINEEND_LF:   nLineEndType = ::com::sun::star::awt::LineEndFormat::LINE_FEED; break;
                case LINEEND_CRLF: nLineEndType = ::com::sun::star::awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED; break;
                default: DBG_ERROR( "VCLXMultiLineEdit::getProperty: invalid line end value!" ); break;
                }
                aProp <<= nLineEndType;
            }
            break;

			case BASEPROPERTY_READONLY:
			{
				aProp <<= pMultiLineEdit->IsReadOnly();
			}
			break;
			case BASEPROPERTY_MAXTEXTLEN:
			{
				aProp <<= (sal_Int16) pMultiLineEdit->GetMaxTextLen();
			}
			break;
			default:
			{
				aProp <<= VCLXWindow::getProperty( PropertyName );
			}
		}
	}
	return aProp;
}

void SAL_CALL VCLXMultiLineEdit::setFocus(  ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

    // don't grab the focus if we already have it. Reason is that the only thing which the edit
    // does is forwarding the focus to it's text window. This text window then does a "select all".
    // So if the text window already has the focus, and we give the focus to the multi line
    // edit, then all which happens is that everything is selected.
    // #i27072# - 2004-04-25 - fs@openoffice.org
    if ( GetWindow() && !GetWindow()->HasChildPathFocus() )
		GetWindow()->GrabFocus();
}

void VCLXMultiLineEdit::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     // FIXME: elide duplication ?
                     BASEPROPERTY_LINE_END_FORMAT,
                     BASEPROPERTY_READONLY,
                     BASEPROPERTY_MAXTEXTLEN,
                     BASEPROPERTY_HIDEINACTIVESELECTION,
                     0);
    VCLXWindow::ImplGetPropertyIds( rIds, true );

}
//	----------------------------------------------------
//	class VCLXFileControl
//	----------------------------------------------------
VCLXFileControl::VCLXFileControl() : maTextListeners( *this )
{
}

VCLXFileControl::~VCLXFileControl()
{
	FileControl* pControl = (FileControl*) GetWindow();
	if ( pControl )
		pControl->GetEdit().SetModifyHdl( Link() );
}

::com::sun::star::uno::Any VCLXFileControl::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( ::com::sun::star::awt::XTextComponent*, this ),
										SAL_STATIC_CAST( ::com::sun::star::awt::XTextLayoutConstrains*, this ),
										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
	return (aRet.hasValue() ? aRet : VCLXWindow::queryInterface( rType ));
}

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXFileControl )
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent>* ) NULL ),
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextLayoutConstrains>* ) NULL ),
	VCLXWindow::getTypes()
IMPL_XTYPEPROVIDER_END

void SAL_CALL VCLXFileControl::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pControl = (FileControl*)GetWindow();
	if ( pControl )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch ( nPropType )
		{
        case BASEPROPERTY_HIDEINACTIVESELECTION:
        {
            sal_Bool bValue( sal_False );
            OSL_VERIFY( Value >>= bValue );

            lcl_setWinBits( pControl, WB_NOHIDESELECTION, !bValue );
            lcl_setWinBits( &pControl->GetEdit(), WB_NOHIDESELECTION, !bValue );
        }
        break;

        default:
            VCLXWindow::setProperty( PropertyName, Value );
            break;
        }
    }
}

void VCLXFileControl::SetWindow( Window* pWindow )
{
	FileControl* pPrevFileControl = dynamic_cast<FileControl*>( GetWindow() );
	if ( pPrevFileControl )
		pPrevFileControl->GetEdit().SetModifyHdl( Link() );

	FileControl* pNewFileControl = dynamic_cast<FileControl*>( pWindow );
	if ( pNewFileControl )
		pNewFileControl->GetEdit().SetModifyHdl( LINK( this, VCLXFileControl, ModifyHdl ) );

	VCLXWindow::SetWindow( pWindow );
}

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

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

void VCLXFileControl::setText( const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	Window* pWindow = GetWindow();
	if ( pWindow )
	{
		pWindow->SetText( aText );

		// In JAVA wird auch ein textChanged ausgeloest, in VCL nicht.
		// ::com::sun::star::awt::Toolkit soll JAVA-komform sein...
		ModifyHdl( NULL );
	}
}

void VCLXFileControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl )
	{
		pFileControl->GetEdit().SetSelection( Selection( rSel.Min, rSel.Max ) );
		pFileControl->GetEdit().ReplaceSelected( aText );
	}
}

::rtl::OUString VCLXFileControl::getText() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::rtl::OUString aText;
	Window* pWindow = GetWindow();
	if ( pWindow )
		aText = pWindow->GetText();
	return aText;
}

::rtl::OUString VCLXFileControl::getSelectedText() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::rtl::OUString aText;
	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl)
		aText = pFileControl->GetEdit().GetSelected();
	return aText;

}

void VCLXFileControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl )
		pFileControl->GetEdit().SetSelection( Selection( aSelection.Min, aSelection.Max ) );
}

::com::sun::star::awt::Selection VCLXFileControl::getSelection() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Selection aSel;
	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl )
	{
		aSel.Min = pFileControl->GetEdit().GetSelection().Min();
		aSel.Max = pFileControl->GetEdit().GetSelection().Max();
	}
	return aSel;
}

sal_Bool VCLXFileControl::isEditable() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	return ( pFileControl && !pFileControl->GetEdit().IsReadOnly() && pFileControl->GetEdit().IsEnabled() ) ? sal_True : sal_False;
}

void VCLXFileControl::setEditable( sal_Bool bEditable ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl )
		pFileControl->GetEdit().SetReadOnly( !bEditable );
}

void VCLXFileControl::setMaxTextLen( sal_Int16 nLen ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	if ( pFileControl )
		pFileControl->GetEdit().SetMaxTextLen( nLen );
}

sal_Int16 VCLXFileControl::getMaxTextLen() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FileControl* pFileControl = (FileControl*) GetWindow();
	return pFileControl ? pFileControl->GetEdit().GetMaxTextLen() : 0;
}


IMPL_LINK( VCLXFileControl, ModifyHdl, Edit*, EMPTYARG )
{
	::com::sun::star::awt::TextEvent aEvent;
	aEvent.Source = (::cppu::OWeakObject*)this;
	maTextListeners.textChanged( aEvent );

	return 1;
}

::com::sun::star::awt::Size VCLXFileControl::getMinimumSize() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz;
	FileControl* pControl = (FileControl*) GetWindow();
	if ( pControl )
	{
		Size aTmpSize = pControl->GetEdit().CalcMinimumSize();
		aTmpSize.Width() += pControl->GetButton().CalcMinimumSize().Width();
		aSz = AWTSize(pControl->CalcWindowSize( aTmpSize ));
	}
	return aSz;
}

::com::sun::star::awt::Size VCLXFileControl::getPreferredSize() throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::awt::Size aSz = getMinimumSize();
	aSz.Height += 4;
	return aSz;
}

::com::sun::star::awt::Size VCLXFileControl::calcAdjustedSize( const ::com::sun::star::awt::Size& rNewSize ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz =rNewSize;
	FileControl* pControl = (FileControl*) GetWindow();
	if ( pControl )
	{
		::com::sun::star::awt::Size aMinSz = getMinimumSize();
		if ( aSz.Height != aMinSz.Height )
			aSz.Height = aMinSz.Height;
	}
	return aSz;
}

::com::sun::star::awt::Size VCLXFileControl::getMinimumSize( sal_Int16 nCols, sal_Int16 ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::awt::Size aSz;
	FileControl* pControl = (FileControl*) GetWindow();
	if ( pControl )
	{
		aSz = AWTSize(pControl->GetEdit().CalcSize( nCols ));
		aSz.Width += pControl->GetButton().CalcMinimumSize().Width();
	}
	return aSz;
}

void VCLXFileControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	nCols = 0;
	nLines = 1;
	FileControl* pControl = (FileControl*) GetWindow();
	if ( pControl )
		nCols = (sal_Int16) pControl->GetEdit().GetMaxVisChars();
}

void VCLXFileControl::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     // FIXME: elide duplication ?
                     BASEPROPERTY_HIDEINACTIVESELECTION,
                     0);
    VCLXWindow::ImplGetPropertyIds( rIds, true );
}


//	----------------------------------------------------
//	class SVTXFormattedField
//	----------------------------------------------------
// --------------------------------------------------------------------------------------
SVTXFormattedField::SVTXFormattedField()
	:m_pCurrentSupplier(NULL)
	,bIsStandardSupplier(sal_True)
	,nKeyToSetDelayed(-1)
{
}

// --------------------------------------------------------------------------------------
SVTXFormattedField::~SVTXFormattedField()
{
	if (m_pCurrentSupplier)
	{
		m_pCurrentSupplier->release();
		m_pCurrentSupplier = NULL;
	}
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetWindow( Window* _pWindow )
{
	VCLXSpinField::SetWindow(_pWindow);
	if (GetFormattedField())
		GetFormattedField()->SetAutoColor(sal_True);
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
            case BASEPROPERTY_ENFORCE_FORMAT:
            {
                sal_Bool bEnable( sal_True );
                if ( Value >>= bEnable )
                    pField->EnableNotANumber( !bEnable );
            }
            break;

			case BASEPROPERTY_EFFECTIVE_MIN:
			case BASEPROPERTY_VALUEMIN_DOUBLE:
				SetMinValue(Value);
				break;

			case BASEPROPERTY_EFFECTIVE_MAX:
			case BASEPROPERTY_VALUEMAX_DOUBLE:
				SetMaxValue(Value);
				break;

			case BASEPROPERTY_EFFECTIVE_DEFAULT:
				SetDefaultValue(Value);
				break;

            case BASEPROPERTY_TREATASNUMBER:
            {
                sal_Bool b = sal_Bool();
                if ( Value >>= b )
                    SetTreatAsNumber(b);
            }
            break;

			case BASEPROPERTY_FORMATSSUPPLIER:
				if (!Value.hasValue())
					setFormatsSupplier(::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > (NULL));
				else
				{
					::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > xNFS;
					if ( Value >>= xNFS )
						setFormatsSupplier(xNFS);
				}
				break;
			case BASEPROPERTY_FORMATKEY:
				if (!Value.hasValue())
					setFormatKey(0);
				else
				{
					sal_Int32 n = 0;
					if ( Value >>= n )
						setFormatKey(n);
				}
				break;

			case BASEPROPERTY_EFFECTIVE_VALUE:
			case BASEPROPERTY_VALUE_DOUBLE:
			{
				const ::com::sun::star::uno::TypeClass rTC = Value.getValueType().getTypeClass();
				if (rTC != ::com::sun::star::uno::TypeClass_STRING)
					// no string
					if (rTC != ::com::sun::star::uno::TypeClass_DOUBLE)
						// no double
						if (Value.hasValue())
						{	// but a value
							// try if it is something converitble
							sal_Int32 nValue = 0;
							if (!(Value >>= nValue))
								throw ::com::sun::star::lang::IllegalArgumentException();
							SetValue(::com::sun::star::uno::makeAny((double)nValue));
							break;
						}

				SetValue(Value);
			}
			break;
			case BASEPROPERTY_VALUESTEP_DOUBLE:
			{
				double d = 0.0;
				if ( Value >>= d )
		 			pField->SetSpinSize( d );
				else
				{
					sal_Int32 n = 0;
					if ( Value >>= n )
		 				pField->SetSpinSize( n );
				}
			}
			break;
			case BASEPROPERTY_DECIMALACCURACY:
			{
				sal_Int32 n = 0;
				if ( Value >>= n )
			 		pField->SetDecimalDigits( (sal_uInt16)n );
			}
			break;
			case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
			{
					sal_Bool b = sal_Bool();
					if ( Value >>= b )
			 		pField->SetThousandsSep( b );
			}
			break;

			default:
				VCLXSpinField::setProperty( PropertyName, Value );
		}

		if (BASEPROPERTY_TEXTCOLOR == nPropType)
		{	// after setting a new text color, think again about the AutoColor flag of the control
			// 17.05.2001 - 86859 - frank.schoenheit@germany.sun.com
			pField->SetAutoColor(!Value.hasValue());
		}
	}
	else
		VCLXSpinField::setProperty( PropertyName, Value );
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aReturn;

	FormattedField* pField = GetFormattedField();
	if ( pField )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
			case BASEPROPERTY_EFFECTIVE_MIN:
			case BASEPROPERTY_VALUEMIN_DOUBLE:
				aReturn <<= GetMinValue();
				break;

			case BASEPROPERTY_EFFECTIVE_MAX:
			case BASEPROPERTY_VALUEMAX_DOUBLE:
				aReturn <<= GetMaxValue();
				break;

			case BASEPROPERTY_EFFECTIVE_DEFAULT:
				aReturn <<= GetDefaultValue();
				break;

			case BASEPROPERTY_TREATASNUMBER:
				aReturn <<= GetTreatAsNumber();
				break;

			case BASEPROPERTY_EFFECTIVE_VALUE:
			case BASEPROPERTY_VALUE_DOUBLE:
				aReturn <<= GetValue();
				break;

			case BASEPROPERTY_VALUESTEP_DOUBLE:
				aReturn <<= pField->GetSpinSize();
				break;

			case BASEPROPERTY_DECIMALACCURACY:
				aReturn <<= pField->GetDecimalDigits();
				break;

			case BASEPROPERTY_FORMATSSUPPLIER:
			{
				if (!bIsStandardSupplier)
				{	// ansonsten void
					::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >  xSupplier = getFormatsSupplier();
					aReturn <<= xSupplier;
				}
			}
			break;

			case BASEPROPERTY_FORMATKEY:
			{
				if (!bIsStandardSupplier)
					aReturn <<= getFormatKey();
			}
			break;

			default:
				aReturn <<= VCLXSpinField::getProperty(PropertyName);
		}
	}
	return aReturn;
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::convertEffectiveValue(const ::com::sun::star::uno::Any& rValue)
{
	::com::sun::star::uno::Any aReturn;

	FormattedField* pField = GetFormattedField();
	if (!pField)
		return aReturn;

	switch (rValue.getValueType().getTypeClass())
	{
		case ::com::sun::star::uno::TypeClass_DOUBLE:
			if (pField->TreatingAsNumber())
			{
				double d = 0.0;
				rValue >>= d;
				aReturn <<= d;
			}
			else
			{
				SvNumberFormatter* pFormatter = pField->GetFormatter();
				if (!pFormatter)
					pFormatter = pField->StandardFormatter();
					// should never fail

				Color* pDum;
				double d = 0.0;
				rValue >>= d;
				String sConverted;
				pFormatter->GetOutputString(d, 0, sConverted, &pDum);
				aReturn <<= ::rtl::OUString( sConverted );
			}
			break;
		case ::com::sun::star::uno::TypeClass_STRING:
		{
			::rtl::OUString aStr;
			rValue >>= aStr;
			String sValue = aStr;
			if (pField->TreatingAsNumber())
			{
				SvNumberFormatter* pFormatter = pField->GetFormatter();
				if (!pFormatter)
					pFormatter = pField->StandardFormatter();

				double dVal;
				sal_uInt32 nTestFormat(0);
				if (!pFormatter->IsNumberFormat(sValue, nTestFormat, dVal))
					aReturn.clear();
				aReturn <<=dVal;
			}
			else
				aReturn <<= aStr;
		}
		break;
		default:
			aReturn.clear();
			break;
	}
	return aReturn;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetMinValue(const ::com::sun::star::uno::Any& rValue)
{
	FormattedField* pField = GetFormattedField();
	if (!pField)
		return;

	switch (rValue.getValueType().getTypeClass())

	{
		case ::com::sun::star::uno::TypeClass_DOUBLE:
        {
			double d = 0.0;
			rValue >>= d;
			pField->SetMinValue(d);
        }
			break;
		default:
			DBG_ASSERT(rValue.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_VOID, "SVTXFormattedField::SetMinValue : invalid argument (an exception will be thrown) !");
			if ( rValue.getValueType().getTypeClass() != ::com::sun::star::uno::TypeClass_VOID )

			{
				throw ::com::sun::star::lang::IllegalArgumentException();
			}
			pField->ClearMinValue();
			break;
	}
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::GetMinValue()
{
	FormattedField* pField = GetFormattedField();
	if (!pField || !pField->HasMinValue())
		return ::com::sun::star::uno::Any();

	::com::sun::star::uno::Any aReturn;
	aReturn <<= pField->GetMinValue();
	return aReturn;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetMaxValue(const ::com::sun::star::uno::Any& rValue)
{
	FormattedField* pField = GetFormattedField();
	if (!pField)
		return;

	switch (rValue.getValueType().getTypeClass())

	{
		case ::com::sun::star::uno::TypeClass_DOUBLE:
        {
			double d = 0.0;
			rValue >>= d;
			pField->SetMaxValue(d);
        }
			break;
		default:
			if (rValue.getValueType().getTypeClass() != ::com::sun::star::uno::TypeClass_VOID)

			{
				throw ::com::sun::star::lang::IllegalArgumentException();
			}
			pField->ClearMaxValue();
			break;
	}
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::GetMaxValue()
{
	FormattedField* pField = GetFormattedField();
	if (!pField || !pField->HasMaxValue())
		return ::com::sun::star::uno::Any();

	::com::sun::star::uno::Any aReturn;
	aReturn <<= pField->GetMaxValue();
	return aReturn;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetDefaultValue(const ::com::sun::star::uno::Any& rValue)
{
	FormattedField* pField = GetFormattedField();
	if (!pField)
		return;

	::com::sun::star::uno::Any aConverted = convertEffectiveValue(rValue);

	switch (aConverted.getValueType().getTypeClass())

	{
		case ::com::sun::star::uno::TypeClass_DOUBLE:
		{
			double d = 0.0;
			aConverted >>= d;
			pField->SetDefaultValue(d);
		}
		break;
		case ::com::sun::star::uno::TypeClass_STRING:
		{
			::rtl::OUString aStr;
			aConverted >>= aStr;
			pField->SetDefaultText( aStr );
		}
		break;
		default:
			pField->EnableEmptyField(sal_True);
				// nur noch void erlaubt
			break;
	}
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::GetDefaultValue()
{
	FormattedField* pField = GetFormattedField();
	if (!pField || pField->IsEmptyFieldEnabled())
		return ::com::sun::star::uno::Any();

	::com::sun::star::uno::Any aReturn;
	if (pField->TreatingAsNumber())
		aReturn <<= pField->GetDefaultValue();
	else
		aReturn <<= ::rtl::OUString( pField->GetDefaultText() );
	return aReturn;
}

// --------------------------------------------------------------------------------------
sal_Bool SVTXFormattedField::GetTreatAsNumber()
{
	FormattedField* pField = GetFormattedField();
	if (pField)
		return pField->TreatingAsNumber();

	return sal_True;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetTreatAsNumber(sal_Bool bSet)
{
	FormattedField* pField = GetFormattedField();
	if (pField)
		pField->TreatAsNumber(bSet);
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXFormattedField::GetValue()
{
	FormattedField* pField = GetFormattedField();
	if (!pField)
		return ::com::sun::star::uno::Any();

	::com::sun::star::uno::Any aReturn;
	if (!pField->TreatingAsNumber())
	{
		::rtl::OUString sText = pField->GetTextValue();
		aReturn <<= sText;
	}
	else
	{
		if (pField->GetText().Len())	// empty wird erst mal standardmaessig als void nach draussen gereicht
			aReturn <<= pField->GetValue();
	}

	return aReturn;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::SetValue(const ::com::sun::star::uno::Any& rValue)
{
	FormattedField* pField = GetFormattedField();
	if (!pField)
		return;

	if (!rValue.hasValue())
	{
		pField->SetText(String());
	}
	else
	{
		if (rValue.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_DOUBLE )
		{
			double d = 0.0;
			rValue >>= d;
			pField->SetValue(d);
		}
		else
		{
			DBG_ASSERT(rValue.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_STRING, "SVTXFormattedField::SetValue : invalid argument !");

			::rtl::OUString sText;
			rValue >>= sText;
			String aStr( sText );
			if (!pField->TreatingAsNumber())
				pField->SetTextFormatted(aStr);
			else
				pField->SetTextValue(aStr);
		}
	}
//	NotifyTextListeners();
}

// --------------------------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >  SVTXFormattedField::getFormatsSupplier(void) const
{
	return ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > ((::com::sun::star::util::XNumberFormatsSupplier*)m_pCurrentSupplier);
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::setFormatsSupplier(const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xSupplier)
{
	FormattedField* pField = GetFormattedField();

	SvNumberFormatsSupplierObj* pNew = NULL;
	if (!xSupplier.is())
	{
		if (pField)
		{
			pNew = new SvNumberFormatsSupplierObj(pField->StandardFormatter());
			bIsStandardSupplier = sal_True;
		}
	}
	else
	{
		pNew = SvNumberFormatsSupplierObj::getImplementation(xSupplier);
		bIsStandardSupplier = sal_False;
	}

	if (!pNew)
		return;		// TODO : wie das behandeln ?

	if (m_pCurrentSupplier)
		m_pCurrentSupplier->release();
	m_pCurrentSupplier = pNew;
	m_pCurrentSupplier->acquire();
	if (pField)
	{
		// den aktuellen Value mit hinueberretten
		::com::sun::star::uno::Any aCurrent = GetValue();
		pField->SetFormatter(m_pCurrentSupplier->GetNumberFormatter(), sal_False);
		if (nKeyToSetDelayed != -1)
		{
			pField->SetFormatKey(nKeyToSetDelayed);
			nKeyToSetDelayed = -1;
		}
		SetValue(aCurrent);
		NotifyTextListeners();
	}
}

// --------------------------------------------------------------------------------------
sal_Int32 SVTXFormattedField::getFormatKey(void) const
{
	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetFormatKey() : 0;
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::setFormatKey(sal_Int32 nKey)
{
	FormattedField* pField = GetFormattedField();
	if (pField)
	{
		if (pField->GetFormatter())
			pField->SetFormatKey(nKey);
		else
		{	// Wahrscheinlich bin ich gerade in einem Block, in dem erst der Key und dann der Formatter gesetzt
			// wird, das passiert initial mit ziemlicher Sicherheit, da die Properties in alphabetischer Reihenfolge
			// gesetzt werden, und der FormatsSupplier nun mal vor dem FormatKey kommt
			nKeyToSetDelayed = nKey;
		}
		NotifyTextListeners();
	}
}

// --------------------------------------------------------------------------------------
void SVTXFormattedField::NotifyTextListeners()
{
	if ( GetTextListeners().getLength() )
	{
		::com::sun::star::awt::TextEvent aEvent;
		aEvent.Source = (::cppu::OWeakObject*)this;
		GetTextListeners().textChanged( aEvent );
	}
}

void SVTXFormattedField::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     // FIXME: elide duplication ?
                     BASEPROPERTY_EFFECTIVE_MIN,
                     BASEPROPERTY_VALUEMIN_DOUBLE,
                     BASEPROPERTY_EFFECTIVE_MAX,
                     BASEPROPERTY_VALUEMAX_DOUBLE,
                     BASEPROPERTY_EFFECTIVE_DEFAULT,
                     BASEPROPERTY_TREATASNUMBER,
                     BASEPROPERTY_EFFECTIVE_VALUE,
                     BASEPROPERTY_VALUE_DOUBLE,
                     BASEPROPERTY_VALUESTEP_DOUBLE,
                     BASEPROPERTY_DECIMALACCURACY,
                     BASEPROPERTY_FORMATSSUPPLIER,
                     BASEPROPERTY_NUMSHOWTHOUSANDSEP,
                     BASEPROPERTY_FORMATKEY,
                     BASEPROPERTY_TREATASNUMBER,
                     BASEPROPERTY_ENFORCE_FORMAT,
                     0);
    VCLXWindow::ImplGetPropertyIds( rIds, true );
    VCLXSpinField::ImplGetPropertyIds( rIds );
}


//	----------------------------------------------------
//	class SVTXRoadmap
//	----------------------------------------------------

using namespace svt;

// --------------------------------------------------------------------------------------
SVTXRoadmap::SVTXRoadmap() : maItemListeners( *this )
{
}

// --------------------------------------------------------------------------------------
SVTXRoadmap::~SVTXRoadmap()
{
}

void SVTXRoadmap::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
{
	switch ( rVclWindowEvent.GetId() )
	{
		case VCLEVENT_ROADMAP_ITEMSELECTED:
        {
        	::vos::OGuard aGuard( GetMutex() );
            ::svt::ORoadmap* pField = GetRoadmap();
	        if ( pField )
	        {
                sal_Int16 CurItemID = pField->GetCurrentRoadmapItemID();
                ::com::sun::star::awt::ItemEvent aEvent;
                aEvent.Selected = CurItemID;
                aEvent.Highlighted = CurItemID;
                aEvent.ItemId = CurItemID;
                maItemListeners.itemStateChanged( aEvent );
            }
        }
        break;
		default:
            SVTXRoadmap_Base::ProcessWindowEvent( rVclWindowEvent );
		    break;
	}
}


void SVTXRoadmap::propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );
    ::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRoadmapItem;
        xRoadmapItem = evt.Source;
        sal_Int32 nID = 0;
        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropertySet( xRoadmapItem, ::com::sun::star::uno::UNO_QUERY );
        ::com::sun::star::uno::Any aValue = xPropertySet->getPropertyValue(::rtl::OUString::createFromAscii( "ID" ));
        aValue >>= nID;

        ::com::sun::star::uno::Any rVal = evt.NewValue;
        evt.NewValue >>= rVal;
        ::rtl::OUString sPropertyName = evt.PropertyName;
        if ( sPropertyName.equals(::rtl::OUString::createFromAscii( "Enabled" ) ) )
        {
            sal_Bool bEnable = false;
            evt.NewValue >>= bEnable;
            pField->EnableRoadmapItem( (RoadmapTypes::ItemId)nID , bEnable );
        }
        else if ( sPropertyName.equals(::rtl::OUString::createFromAscii( "Label" ) ) )
        {
            ::rtl::OUString sLabel;
            evt.NewValue >>= sLabel;
            pField->ChangeRoadmapItemLabel( (RoadmapTypes::ItemId)nID , sLabel );
        }
        else if  ( sPropertyName.equals(::rtl::OUString::createFromAscii( "ID" ) ) )
        {
            sal_Int32 nNewID = 0;
            evt.NewValue >>= nNewID;
            evt.OldValue >>= nID;
            pField->ChangeRoadmapItemID( (RoadmapTypes::ItemId)nID, (RoadmapTypes::ItemId)nNewID );
        }
    //    else
            // Todo: handle Interactive appropriately
    }
}


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

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

RMItemData SVTXRoadmap::GetRMItemData( const ::com::sun::star::container::ContainerEvent& _rEvent )
{
    RMItemData aCurRMItemData;
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRoadmapItem;
	_rEvent.Element >>= xRoadmapItem;
    ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropertySet( xRoadmapItem, ::com::sun::star::uno::UNO_QUERY );
	if ( xPropertySet.is() )
    {
        ::com::sun::star::uno::Any aValue = xPropertySet->getPropertyValue(::rtl::OUString::createFromAscii( "Label" ));
        aValue >>= aCurRMItemData.Label;
        aValue = xPropertySet->getPropertyValue(::rtl::OUString::createFromAscii( "ID" ));
        aValue >>= aCurRMItemData.n_ID;
        aValue = xPropertySet->getPropertyValue(::rtl::OUString::createFromAscii( "Enabled" ));
        aValue >>= aCurRMItemData.b_Enabled;
    }
    return aCurRMItemData;;
}

void SVTXRoadmap::elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent )throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );
    ::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
        RMItemData CurItemData = GetRMItemData(  _rEvent );
        sal_Int32 InsertIndex = 0;
        _rEvent.Accessor >>= InsertIndex;
        pField->InsertRoadmapItem( InsertIndex, CurItemData.Label, (RoadmapTypes::ItemId)CurItemData.n_ID, CurItemData.b_Enabled );
    }
}

void SVTXRoadmap::elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent )throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );
    ::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
        sal_Int32 DelIndex = 0;
        _rEvent.Accessor >>= DelIndex;
        pField->DeleteRoadmapItem(DelIndex);
//        pField->GetCurrentRoadmapItem()
//        setProperty(::rtl::OUString.createFromAscii( "CurrentItem" )aAny,
    }
}

void SVTXRoadmap::elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent )throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );
    ::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
        RMItemData CurItemData = GetRMItemData(  _rEvent );
        sal_Int32 ReplaceIndex = 0;
        _rEvent.Accessor >>= ReplaceIndex;
        pField->ReplaceRoadmapItem( ReplaceIndex, CurItemData.Label, (RoadmapTypes::ItemId)CurItemData.n_ID, CurItemData.b_Enabled );
    }
}



// --------------------------------------------------------------------------------------
void SVTXRoadmap::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

    ::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
			case BASEPROPERTY_COMPLETE:
            {
                sal_Bool b = false;
	    		Value >>= b;
                pField->SetRoadmapComplete( b);
            }
            break;

			case BASEPROPERTY_ACTIVATED:
            {
   		    	sal_Bool b = false;
	    		Value >>= b;
                pField->SetRoadmapInteractive( b);
            }
			break;

            case BASEPROPERTY_CURRENTITEMID:
            {
   				sal_Int32 nId = 0;
				Value >>= nId;
                pField->SelectRoadmapItemByID( (RoadmapTypes::ItemId)nId );
            }
            break;

            case BASEPROPERTY_TEXT:
            {
   				::rtl::OUString aStr;
				Value >>= aStr;
                pField->SetText( aStr );
                pField->Invalidate();
            }
            break;

            default:
				SVTXRoadmap_Base::setProperty( PropertyName, Value );
                break;
		}

	}
	else
		SVTXRoadmap_Base::setProperty( PropertyName, Value );
}


// --------------------------------------------------------------------------------------
::com::sun::star::uno::Any SVTXRoadmap::getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aReturn;

	::svt::ORoadmap* pField = GetRoadmap();
	if ( pField )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
			case BASEPROPERTY_COMPLETE:
                aReturn <<= pField->IsRoadmapComplete();
                break;
			case BASEPROPERTY_ACTIVATED:
                aReturn <<= pField->IsRoadmapInteractive();
				break;
			case BASEPROPERTY_CURRENTITEMID:
                aReturn <<= pField->GetCurrentRoadmapItemID();
                break;
            default:
				aReturn = SVTXRoadmap_Base::getProperty(PropertyName);
                break;
		}
	}
	return aReturn;
}

void SVTXRoadmap::ImplSetNewImage()
{
    OSL_PRECOND( GetWindow(), "SVTXRoadmap::ImplSetNewImage: window is required to be not-NULL!" );
	::svt::ORoadmap* pButton = static_cast< ::svt::ORoadmap* >( GetWindow() );
	pButton->SetRoadmapBitmap( GetImage().GetBitmapEx() );
}

void SVTXRoadmap::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     BASEPROPERTY_COMPLETE,
                     BASEPROPERTY_ACTIVATED,
                     BASEPROPERTY_CURRENTITEMID,
                     BASEPROPERTY_TEXT,
                     0);
    VCLXWindow::ImplGetPropertyIds( rIds, true );
    VCLXGraphicControl::ImplGetPropertyIds( rIds );
}

//	----------------------------------------------------
//	class SVTXNumericField
//	----------------------------------------------------
SVTXNumericField::SVTXNumericField()
{
}

SVTXNumericField::~SVTXNumericField()
{
}

::com::sun::star::uno::Any SVTXNumericField::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( ::com::sun::star::awt::XNumericField*, this ),
										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
	return (aRet.hasValue() ? aRet : SVTXFormattedField::queryInterface( rType ));
}

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( SVTXNumericField )
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XNumericField>* ) NULL ),
	SVTXFormattedField::getTypes()
IMPL_XTYPEPROVIDER_END


void SVTXNumericField::setValue( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetValue( Value );
}

double SVTXNumericField::getValue() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetValue() : 0;
}

void SVTXNumericField::setMin( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetMinValue( Value );
}

double SVTXNumericField::getMin() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetMinValue() : 0;
}

void SVTXNumericField::setMax( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetMaxValue( Value );
}

double SVTXNumericField::getMax() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetMaxValue() : 0;
}

void SVTXNumericField::setFirst( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinFirst( Value );
}

double SVTXNumericField::getFirst() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinFirst() : 0;
}

void SVTXNumericField::setLast( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinLast( Value );
}

double SVTXNumericField::getLast() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinLast() : 0;
}

void SVTXNumericField::setSpinSize( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinSize( Value );
}

double SVTXNumericField::getSpinSize() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinSize() : 0;
}

void SVTXNumericField::setDecimalDigits( sal_Int16 Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetDecimalDigits( Value );
}

sal_Int16 SVTXNumericField::getDecimalDigits() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetDecimalDigits() : 0;
}

void SVTXNumericField::setStrictFormat( sal_Bool bStrict ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetStrictFormat( bStrict );
}

sal_Bool SVTXNumericField::isStrictFormat() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->IsStrictFormat() : sal_False;
}

void SVTXNumericField::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    SVTXFormattedField::ImplGetPropertyIds( rIds );
}

//	----------------------------------------------------
//	class SVTXCurrencyField
//	----------------------------------------------------
SVTXCurrencyField::SVTXCurrencyField()
{
}

SVTXCurrencyField::~SVTXCurrencyField()
{
}

::com::sun::star::uno::Any SVTXCurrencyField::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( ::com::sun::star::awt::XCurrencyField*, this ),
										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
	return (aRet.hasValue() ? aRet : SVTXFormattedField::queryInterface( rType ));
}

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( SVTXCurrencyField )
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XCurrencyField>* ) NULL ),
	SVTXFormattedField::getTypes()
IMPL_XTYPEPROVIDER_END

void SVTXCurrencyField::setValue( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetValue( Value );
}

double SVTXCurrencyField::getValue() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetValue() : 0;
}

void SVTXCurrencyField::setMin( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetMinValue( Value );
}

double SVTXCurrencyField::getMin() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetMinValue() : 0;
}

void SVTXCurrencyField::setMax( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetMaxValue( Value );
}

double SVTXCurrencyField::getMax() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetMaxValue() : 0;
}

void SVTXCurrencyField::setFirst( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinFirst( Value );
}

double SVTXCurrencyField::getFirst() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinFirst() : 0;
}

void SVTXCurrencyField::setLast( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinLast( Value );
}

double SVTXCurrencyField::getLast() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinLast() : 0;
}

void SVTXCurrencyField::setSpinSize( double Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetSpinSize( Value );
}

double SVTXCurrencyField::getSpinSize() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetSpinSize() : 0;
}

void SVTXCurrencyField::setDecimalDigits( sal_Int16 Value ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetDecimalDigits( Value );
}

sal_Int16 SVTXCurrencyField::getDecimalDigits() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->GetDecimalDigits() : 0;
}

void SVTXCurrencyField::setStrictFormat( sal_Bool bStrict ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	if ( pField )
		pField->SetStrictFormat( bStrict );
}

sal_Bool SVTXCurrencyField::isStrictFormat() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	FormattedField* pField = GetFormattedField();
	return pField ? pField->IsStrictFormat() : sal_False;
}

void SVTXCurrencyField::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aReturn;

	DoubleCurrencyField* pField = (DoubleCurrencyField*)GetFormattedField();
	if ( pField )
	{
#ifdef DBG_UTIL
		String sAssertion( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "SVTXCurrencyField::setProperty(" ) ) );
		sAssertion += String( PropertyName );
		sAssertion.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ") : invalid value !" ) );
#endif
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
			case BASEPROPERTY_CURRENCYSYMBOL:
			{
				::rtl::OUString aStr;
				Value >>= aStr;
				pField->setCurrencySymbol( aStr );
			}
			break;
			case BASEPROPERTY_CURSYM_POSITION:
			{
				sal_Bool b = false;
				Value >>= b;
				pField->setPrependCurrSym(b);
			}
			break;

			default:
				SVTXFormattedField::setProperty(PropertyName, Value);
		}
	}
	else
		SVTXFormattedField::setProperty(PropertyName, Value);
}

::com::sun::star::uno::Any SVTXCurrencyField::getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aReturn;

	DoubleCurrencyField* pField = (DoubleCurrencyField*)GetFormattedField();
	if ( pField )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch (nPropType)
		{
			case BASEPROPERTY_CURRENCYSYMBOL:
			{
				aReturn <<= ::rtl::OUString( pField->getCurrencySymbol() );
			}
			break;
			case BASEPROPERTY_CURSYM_POSITION:
			{
				aReturn <<= pField->getPrependCurrSym();
			}
			break;
			default:
				return SVTXFormattedField::getProperty(PropertyName);
		}
	}
	return SVTXFormattedField::getProperty(PropertyName);
}

void SVTXCurrencyField::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     BASEPROPERTY_CURRENCYSYMBOL,
                     BASEPROPERTY_CURSYM_POSITION,
                     0);
    SVTXFormattedField::ImplGetPropertyIds( rIds );
}


//	----------------------------------------------------
//	class VCLXProgressBar
//	----------------------------------------------------

VCLXProgressBar::VCLXProgressBar()
			:m_nValue(0)
			,m_nValueMin(0)
			,m_nValueMax(100)
{
}

VCLXProgressBar::~VCLXProgressBar()
{
}

void VCLXProgressBar::ImplUpdateValue()
{
	ProgressBar* pProgressBar = (ProgressBar*) GetWindow();
	if ( pProgressBar )
	{
		sal_Int32 nVal;
		sal_Int32 nValMin;
		sal_Int32 nValMax;

		// check min and max
		if (m_nValueMin < m_nValueMax)
		{
			nValMin = m_nValueMin;
			nValMax = m_nValueMax;
		}
		else
		{
			nValMin = m_nValueMax;
			nValMax = m_nValueMin;
		}

		// check value
		if (m_nValue < nValMin)
		{
			nVal = nValMin;
		}
		else if (m_nValue > nValMax)
		{
			nVal = nValMax;
		}
		else
		{
			nVal = m_nValue;
		}

		// calculate percent
		sal_Int32 nPercent;
		if (nValMin != nValMax)
		{
			nPercent = 100 * (nVal - nValMin) / (nValMax - nValMin);
		}
		else
		{
			nPercent = 0;
		}

		// set progressbar value
		pProgressBar->SetValue( (sal_uInt16) nPercent );
	}
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXProgressBar::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
										SAL_STATIC_CAST( ::com::sun::star::awt::XProgressBar*, this ),
										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
	return (aRet.hasValue() ? aRet : VCLXWindow::queryInterface( rType ));
}

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXProgressBar )
	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XProgressBar>* ) NULL ),
	VCLXWindow::getTypes()
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XProgressBar
void VCLXProgressBar::setForegroundColor( sal_Int32 nColor ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	Window* pWindow = GetWindow();
	if ( pWindow )
	{
		Color aColor( nColor );
		pWindow->SetControlForeground( aColor );
	}
}

void VCLXProgressBar::setBackgroundColor( sal_Int32 nColor ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	Window* pWindow = GetWindow();
	if ( pWindow )
	{
		Color aColor( nColor );
		pWindow->SetBackground( aColor );
		pWindow->SetControlBackground( aColor );
		pWindow->Invalidate();
	}
}

void VCLXProgressBar::setValue( sal_Int32 nValue ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	m_nValue = nValue;
	ImplUpdateValue();
}

void VCLXProgressBar::setRange( sal_Int32 nMin, sal_Int32 nMax ) throw(::com::sun::star::uno::RuntimeException )
{
	::vos::OGuard aGuard( GetMutex() );

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

	ImplUpdateValue();
}

sal_Int32 VCLXProgressBar::getValue() throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	return m_nValue;
}

// ::com::sun::star::awt::VclWindowPeer
void VCLXProgressBar::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

    ProgressBar* pProgressBar = (ProgressBar*)GetWindow();
    if ( pProgressBar )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch ( nPropType )
		{
			case BASEPROPERTY_PROGRESSVALUE:
			{
				if ( Value >>= m_nValue )
					ImplUpdateValue();
			}
			break;
			case BASEPROPERTY_PROGRESSVALUE_MIN:
			{
				if ( Value >>= m_nValueMin )
					ImplUpdateValue();
			}
			break;
			case BASEPROPERTY_PROGRESSVALUE_MAX:
			{
				if ( Value >>= m_nValueMax )
					ImplUpdateValue();
			}
			break;
			case BASEPROPERTY_FILLCOLOR:
			{
				Window* pWindow = GetWindow();
				if ( pWindow )
				{
					sal_Bool bVoid = Value.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_VOID;

					if ( bVoid )
					{
						pWindow->SetControlForeground();
					}
					else
					{
						sal_Int32 nColor = 0;
						if ( Value >>= nColor )
						{
							Color aColor( nColor );
							pWindow->SetControlForeground( aColor );
						}
					}
				}
			}
			break;
			default:
				VCLXWindow::setProperty( PropertyName, Value );
                break;
		}
	}
}

::com::sun::star::uno::Any VCLXProgressBar::getProperty( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::uno::RuntimeException)
{
	::vos::OGuard aGuard( GetMutex() );

	::com::sun::star::uno::Any aProp;
    ProgressBar* pProgressBar = (ProgressBar*)GetWindow();
    if ( pProgressBar )
	{
		sal_uInt16 nPropType = GetPropertyId( PropertyName );
		switch ( nPropType )
		{
			case BASEPROPERTY_PROGRESSVALUE:
			{
 				aProp <<= m_nValue;
			}
			break;
			case BASEPROPERTY_PROGRESSVALUE_MIN:
			{
 				aProp <<= m_nValueMin;
			}
			break;
			case BASEPROPERTY_PROGRESSVALUE_MAX:
			{
 				aProp <<= m_nValueMax;
			}
			break;
            default:
				aProp <<= VCLXWindow::getProperty( PropertyName );
                break;
		}
	}
	return aProp;
}

void VCLXProgressBar::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     BASEPROPERTY_PROGRESSVALUE,
                     BASEPROPERTY_PROGRESSVALUE_MIN,
                     BASEPROPERTY_PROGRESSVALUE_MAX,
                     BASEPROPERTY_FILLCOLOR,
                     0);
    VCLXWindow::ImplGetPropertyIds( rIds, true );
}


//	----------------------------------------------------
//	class SVTXDateField
//	----------------------------------------------------
SVTXDateField::SVTXDateField()
    :VCLXDateField()
{
}

SVTXDateField::~SVTXDateField()
{
}

void SAL_CALL SVTXDateField::setProperty( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Any& Value ) throw(::com::sun::star::uno::RuntimeException)
{
    VCLXDateField::setProperty( PropertyName, Value );

    // some properties need to be forwarded to the sub edit, too
    Edit* pSubEdit = GetWindow() ? static_cast< Edit* >( GetWindow() )->GetSubEdit() : NULL;
    if ( !pSubEdit )
        return;

    switch ( GetPropertyId( PropertyName ) )
    {
    case BASEPROPERTY_TEXTLINECOLOR:
        if ( !Value.hasValue() )
            pSubEdit->SetTextLineColor();
        else
        {
            sal_Int32 nColor = 0;
            if ( Value >>= nColor )
                pSubEdit->SetTextLineColor( Color( nColor ) );
        }
        break;
    }
}

void SVTXDateField::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
{
    PushPropertyIds( rIds,
                     BASEPROPERTY_TEXTLINECOLOR,
                     0);
    VCLXDateField::ImplGetPropertyIds( rIds );
}
