/**************************************************************
 *
 * 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 "toolkit/controls/tkscrollbar.hxx"
#include "toolkit/helper/property.hxx"
#include "toolkit/helper/unopropertyarrayhelper.hxx"
#include <cppuhelper/typeprovider.hxx>
#include <tools/debug.hxx>

// for introspection
#include <toolkit/awt/vclxwindows.hxx>

//........................................................................
namespace toolkit
{
//........................................................................

    using namespace ::com::sun::star;

    //====================================================================
	//= UnoControlScrollBarModel
	//====================================================================
	//--------------------------------------------------------------------
    UnoControlScrollBarModel::UnoControlScrollBarModel( const uno::Reference< lang::XMultiServiceFactory >& i_factory )
        :UnoControlModel( i_factory )
    {
        UNO_CONTROL_MODEL_REGISTER_PROPERTIES( VCLXScrollBar );
    }

	//--------------------------------------------------------------------
    ::rtl::OUString UnoControlScrollBarModel::getServiceName( ) throw(::com::sun::star::uno::RuntimeException)
    {
	    return ::rtl::OUString::createFromAscii( szServiceName_UnoControlScrollBarModel );
    }

	//--------------------------------------------------------------------
    uno::Any UnoControlScrollBarModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
    {
        switch ( nPropId )
        {
        case BASEPROPERTY_LIVE_SCROLL:
            return uno::makeAny( (sal_Bool)sal_False );
        case BASEPROPERTY_DEFAULTCONTROL:
            return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoControlScrollBar ) );

        default:
    	    return UnoControlModel::ImplGetDefaultValue( nPropId );
        }
    }

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

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


    //====================================================================
	//= UnoControlScrollBarModel
	//====================================================================
    UnoScrollBarControl::UnoScrollBarControl( const uno::Reference< lang::XMultiServiceFactory >& i_factory )
        :UnoControlBase( i_factory )
	    ,maAdjustmentListeners( *this )
    {
    }

    ::rtl::OUString UnoScrollBarControl::GetComponentServiceName()
    {
	    return ::rtl::OUString::createFromAscii( "ScrollBar" );
    }

    // ::com::sun::star::uno::XInterface
    uno::Any UnoScrollBarControl::queryAggregation( const uno::Type & rType ) throw(uno::RuntimeException)
    {
	    uno::Any aRet = ::cppu::queryInterface( rType,
										    SAL_STATIC_CAST( awt::XAdjustmentListener*, this ),
										    SAL_STATIC_CAST( awt::XScrollBar*, this ) );
	    return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
    }

    // ::com::sun::star::lang::XTypeProvider
    IMPL_XTYPEPROVIDER_START( UnoScrollBarControl )
	    getCppuType( ( uno::Reference< awt::XAdjustmentListener>* ) NULL ),
	    getCppuType( ( uno::Reference< awt::XScrollBar>* ) NULL ),
	    UnoControlBase::getTypes()
    IMPL_XTYPEPROVIDER_END

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

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

	    uno::Reference < awt::XScrollBar >  xScrollBar( getPeer(), uno::UNO_QUERY );
	    xScrollBar->addAdjustmentListener( this );
    }

    // ::com::sun::star::awt::XAdjustmentListener
    void UnoScrollBarControl::adjustmentValueChanged( const ::com::sun::star::awt::AdjustmentEvent& rEvent ) throw(::com::sun::star::uno::RuntimeException)
    {
	    switch ( rEvent.Type )
	    {
		    case ::com::sun::star::awt::AdjustmentType_ADJUST_LINE:
		    case ::com::sun::star::awt::AdjustmentType_ADJUST_PAGE:
		    case ::com::sun::star::awt::AdjustmentType_ADJUST_ABS:
		    {
			    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );

			    if ( xScrollBar.is() )
			    {
				    uno::Any aAny;
				    aAny <<= xScrollBar->getValue();
				    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), aAny, sal_False );
			    }
		    }
		    break;
		    default:
		    {
                DBG_ERROR( "UnoScrollBarControl::adjustmentValueChanged - unknown Type" );

		    }
	    }

	    if ( maAdjustmentListeners.getLength() )
		    maAdjustmentListeners.adjustmentValueChanged( rEvent );
    }

    // ::com::sun::star::awt::XScrollBar
    void UnoScrollBarControl::addAdjustmentListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XAdjustmentListener > & l ) throw(::com::sun::star::uno::RuntimeException)
    {
	    maAdjustmentListeners.addInterface( l );
    }

    void UnoScrollBarControl::removeAdjustmentListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XAdjustmentListener > & l ) throw(::com::sun::star::uno::RuntimeException)
    {
	    maAdjustmentListeners.removeInterface( l );
    }

    void UnoScrollBarControl::setValue( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), uno::makeAny( n ), sal_True );
    }

    void UnoScrollBarControl::setValues( sal_Int32 nValue, sal_Int32 nVisible, sal_Int32 nMax ) throw(::com::sun::star::uno::RuntimeException)
    {
	    uno::Any aAny;
	    aAny <<= nValue;
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), aAny, sal_True );
	    aAny <<= nVisible;
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VISIBLESIZE ), aAny, sal_True );
	    aAny <<= nMax;
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE_MAX ), aAny, sal_True );
    }

    sal_Int32 UnoScrollBarControl::getValue() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getValue();
	    }
	    return n;
    }

    void UnoScrollBarControl::setMaximum( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE_MAX ), uno::makeAny( n ), sal_True );
    }

    sal_Int32 UnoScrollBarControl::getMaximum() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getMaximum();
	    }
	    return n;
    }

    void UnoScrollBarControl::setLineIncrement( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINEINCREMENT ), uno::makeAny( n ), sal_True );
    }

    sal_Int32 UnoScrollBarControl::getLineIncrement() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getLineIncrement();
	    }
	    return n;
    }

    void UnoScrollBarControl::setBlockIncrement( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_BLOCKINCREMENT ), uno::makeAny( n ), sal_True );
    }

    sal_Int32 UnoScrollBarControl::getBlockIncrement() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getBlockIncrement();
	    }
	    return n;
    }

    void UnoScrollBarControl::setVisibleSize( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VISIBLESIZE ), uno::makeAny( n ), sal_True );
    }

    sal_Int32 UnoScrollBarControl::getVisibleSize() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getVisibleSize();
	    }
	    return n;
    }

    void UnoScrollBarControl::setOrientation( sal_Int32 n ) throw(::com::sun::star::uno::RuntimeException)
    {
	    ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ORIENTATION ), uno::makeAny( n ), sal_True );
    }

    sal_Int32 UnoScrollBarControl::getOrientation() throw(::com::sun::star::uno::RuntimeException)
    {
	    sal_Int32 n = 0;
	    if ( getPeer().is() )
	    {
		    uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
		    n = xScrollBar->getOrientation();
	    }
	    return n;
    }



//........................................................................
}  // namespace toolkit
//........................................................................
