/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_fpicker.hxx"

#include "OfficeFilePicker.hxx"
#include "iodlg.hxx"

#ifndef _LIST_
#include <list>
#endif
#ifndef _FUNCTIONAL_
#include <functional>
#endif
#ifndef _ALGORITHM_
#include <algorithm>
#endif
#include <tools/urlobj.hxx>
#include <tools/debug.hxx>
#define _SVSTDARR_STRINGSDTOR
#include "svl/svstdarr.hxx"
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/ui/dialogs/FilePickerEvent.hpp>
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/beans/StringPair.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
#include <unotools/ucbhelper.hxx>
#include <unotools/pathoptions.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/typeprovider.hxx>
#include "vos/mutex.hxx"
#ifndef _SV_APP_HXX
#include "vcl/svapp.hxx"
#endif

// define ----------------------------------------------------------------

#define MAKE_ANY    ::com::sun::star::uno::makeAny

// using ----------------------------------------------------------------

using namespace     ::com::sun::star::container;
using namespace     ::com::sun::star::lang;
using namespace     ::com::sun::star::ui::dialogs;
using namespace     ::com::sun::star::uno;
using namespace     ::com::sun::star::beans;
using namespace     ::com::sun::star::awt;
using namespace     ::utl;

//=====================================================================

//=====================================================================

struct FilterEntry
{
protected:
	::rtl::OUString		m_sTitle;
	::rtl::OUString		m_sFilter;

	UnoFilterList		m_aSubFilters;

public:
	FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter )
		:m_sTitle( _rTitle )
		,m_sFilter( _rFilter )
	{
	}

	FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters );

	::rtl::OUString		getTitle() const { return m_sTitle; }
	::rtl::OUString		getFilter() const { return m_sFilter; }

	/// determines if the filter has sub filter (i.e., the filter is a filter group in real)
	sal_Bool			hasSubFilters( ) const;

	/** retrieves the filters belonging to the entry
	@return
		the number of sub filters
	*/
	sal_Int32			getSubFilters( UnoFilterList& _rSubFilterList );

	// helpers for iterating the sub filters
	const UnoFilterEntry*	beginSubFilters() const { return m_aSubFilters.getConstArray(); }
	const UnoFilterEntry*	endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); }
};

//=====================================================================

//---------------------------------------------------------------------
FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters )
	:m_sTitle( _rTitle )
	,m_aSubFilters( _rSubFilters )
{
}

//---------------------------------------------------------------------
sal_Bool FilterEntry::hasSubFilters( ) const
{
	return ( 0 < m_aSubFilters.getLength() );
}

//---------------------------------------------------------------------
sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList )
{
	_rSubFilterList = m_aSubFilters;
	return m_aSubFilters.getLength();
}

// struct ElementEntry_Impl ----------------------------------------------

struct ElementEntry_Impl
{
	sal_Int16		m_nElementID;
	sal_Int16		m_nControlAction;
	Any			m_aValue;
	rtl::OUString		m_aLabel;
    sal_Bool        m_bEnabled      : 1;

    sal_Bool        m_bHasValue     : 1;
    sal_Bool        m_bHasLabel     : 1;
    sal_Bool        m_bHasEnabled   : 1;

                    ElementEntry_Impl( sal_Int16 nId );

    void            setValue( const Any& rVal ) { m_aValue = rVal; m_bHasValue = sal_True; }
    void            setAction( sal_Int16 nAction ) { m_nControlAction = nAction; }
    void            setLabel( const rtl::OUString& rVal ) { m_aLabel = rVal; m_bHasLabel = sal_True; }
    void            setEnabled( sal_Bool bEnabled ) { m_bEnabled = bEnabled; m_bHasEnabled = sal_True; }
};

ElementEntry_Impl::ElementEntry_Impl( sal_Int16 nId )
    : m_nElementID( nId )
    , m_nControlAction( 0 )
    , m_bEnabled( sal_False )
    , m_bHasValue( sal_False )
    , m_bHasLabel( sal_False )
    , m_bHasEnabled( sal_False )
{}

//------------------------------------------------------------------------------------
void SvtFilePicker::prepareExecute()
{
	// set the default directory
	// --**-- doesn't match the spec yet
	if ( m_aDisplayDirectory.getLength() > 0 || m_aDefaultName.getLength() > 0 )
	{
		if ( m_aDisplayDirectory.getLength() > 0 )
		{

			INetURLObject aPath( m_aDisplayDirectory );
			if ( m_aDefaultName.getLength() > 0 )
			{
				aPath.insertName( m_aDefaultName );
				getDialog()->SetHasFilename( true );
			}
			String sPath = aPath.GetMainURL( INetURLObject::NO_DECODE );
			getDialog()->SetPath( aPath.GetMainURL( INetURLObject::NO_DECODE ) );
		}
		else if ( m_aDefaultName.getLength() > 0 )
		{
			getDialog()->SetPath( m_aDefaultName );
			getDialog()->SetHasFilename( true );
		}
	}
	else
	{
		// Default-Standard-Dir setzen
		INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() );
		getDialog()->SetPath( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) );
	}

	// set the control values and set the control labels, too
    if ( m_pElemList && !m_pElemList->empty() )
    {
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );

        ElementList::iterator aListIter;
		for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( rEntry.m_bHasValue )
				aAccess.setValue( rEntry.m_nElementID, rEntry.m_nControlAction, rEntry.m_aValue );
            if ( rEntry.m_bHasLabel )
				aAccess.setLabel( rEntry.m_nElementID, rEntry.m_aLabel );
            if ( rEntry.m_bHasEnabled )
				aAccess.enableControl( rEntry.m_nElementID, rEntry.m_bEnabled );
		}

        getDialog()->updateListboxLabelSizes();
    }

    if ( m_pFilterList && !m_pFilterList->empty() )
    {
        for (   FilterList::iterator aListIter = m_pFilterList->begin();
                aListIter != m_pFilterList->end();
                ++aListIter
            )
        {
            if ( aListIter->hasSubFilters() )
            {   // it's a filter group
                UnoFilterList aSubFilters;
                aListIter->getSubFilters( aSubFilters );

                getDialog()->AddFilterGroup( aListIter->getTitle(), aSubFilters );
             }
            else
                // it's a single filter
                getDialog()->AddFilter( aListIter->getTitle(), aListIter->getFilter() );
        }
    }

    // set the default filter
    if ( m_aCurrentFilter.getLength() > 0 )
        getDialog()->SetCurFilter( m_aCurrentFilter );

}

//-----------------------------------------------------------------------------
IMPL_LINK( SvtFilePicker, DialogClosedHdl, Dialog*, pDlg )
{
    if ( m_xDlgClosedListener.is() )
    {
        sal_Int16 nRet = static_cast< sal_Int16 >( pDlg->GetResult() );
        ::com::sun::star::ui::dialogs::DialogClosedEvent aEvent( *this, nRet );
        m_xDlgClosedListener->dialogClosed( aEvent );
        m_xDlgClosedListener.clear();
    }
    return 0;
}

//------------------------------------------------------------------------------------
// SvtFilePicker
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
WinBits SvtFilePicker::getWinBits( WinBits& rExtraBits )
{
	// set the winbits for creating the filedialog
	WinBits nBits = 0L;
    rExtraBits = 0L;

	// set the standard bits acording to the service name
    if ( m_nServiceType == TemplateDescription::FILEOPEN_SIMPLE )
	{
		nBits = WB_OPEN;
	}
	else if ( m_nServiceType == TemplateDescription::FILESAVE_SIMPLE )
	{
		nBits = WB_SAVEAS;
	}
	else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION )
	{
		nBits = WB_SAVEAS;
        rExtraBits = SFX_EXTRA_AUTOEXTENSION;
	}
	else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD )
	{
		nBits = WB_SAVEAS | SFXWB_PASSWORD;
        rExtraBits = SFX_EXTRA_AUTOEXTENSION;
	}
    else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS )
	{
		nBits = WB_SAVEAS | SFXWB_PASSWORD;
        rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_FILTEROPTIONS;
	}
    else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE )
	{
		nBits = WB_SAVEAS;
        rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_TEMPLATES;
	}
    else if ( m_nServiceType == TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION )
	{
		nBits = WB_SAVEAS;
        rExtraBits = SFX_EXTRA_AUTOEXTENSION | SFX_EXTRA_SELECTION;
    }

    else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE )
	{
		nBits = WB_OPEN;
        rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW | SFX_EXTRA_IMAGE_TEMPLATE;
	}
    else if ( m_nServiceType == TemplateDescription::FILEOPEN_PLAY )
	{
		nBits = WB_OPEN;
        rExtraBits = SFX_EXTRA_PLAYBUTTON;
    }
    else if ( m_nServiceType == TemplateDescription::FILEOPEN_READONLY_VERSION )
	{
		nBits = WB_OPEN | SFXWB_READONLY;
        rExtraBits = SFX_EXTRA_SHOWVERSIONS;
	}
    else if ( m_nServiceType == TemplateDescription::FILEOPEN_LINK_PREVIEW )
	{
		nBits = WB_OPEN;
        rExtraBits = SFX_EXTRA_INSERTASLINK | SFX_EXTRA_SHOWPREVIEW;
	}
	if ( m_bMultiSelection && ( ( nBits & WB_OPEN ) == WB_OPEN ) )
		nBits |= SFXWB_MULTISELECTION;

	return nBits;
}

//------------------------------------------------------------------------------------
void SvtFilePicker::notify( sal_Int16 _nEventId, sal_Int16 _nControlId )
{
	if ( !m_xListener.is() )
		return;

    FilePickerEvent aEvent( *this, _nControlId );

	switch ( _nEventId )
	{
		case FILE_SELECTION_CHANGED:
			m_xListener->fileSelectionChanged( aEvent );
			break;
		case DIRECTORY_CHANGED:
			m_xListener->directoryChanged( aEvent );
			break;
		case HELP_REQUESTED:
			m_xListener->helpRequested( aEvent );
			break;
		case CTRL_STATE_CHANGED:
			m_xListener->controlStateChanged( aEvent );
			break;
		case DIALOG_SIZE_CHANGED:
			m_xListener->dialogSizeChanged();
			break;
		default:
			DBG_ERRORFILE( "SvtFilePicker::notify(): Unknown event id!" );
			break;
	}
}

//------------------------------------------------------------------------------------
namespace {
	//................................................................................
	struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool >
	{
	protected:
		const ::rtl::OUString& rTitle;

	public:
		FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { }

		//............................................................................
		bool operator () ( const FilterEntry& _rEntry )
		{
			sal_Bool bMatch;
			if ( !_rEntry.hasSubFilters() )
				// a real filter
				bMatch = ( _rEntry.getTitle() == rTitle );
			else
				// a filter group -> search the sub filters
				bMatch =
					_rEntry.endSubFilters() != ::std::find_if(
						_rEntry.beginSubFilters(),
						_rEntry.endSubFilters(),
						*this
					);

			return bMatch ? true : false;
		}
		bool operator () ( const UnoFilterEntry& _rEntry )
		{
			return _rEntry.First == rTitle ? true : false;
		}
	};
}

//------------------------------------------------------------------------------------
sal_Bool SvtFilePicker::FilterNameExists( const ::rtl::OUString& rTitle )
{
    sal_Bool bRet = sal_False;

    if ( m_pFilterList )
		bRet =
			m_pFilterList->end() != ::std::find_if(
				m_pFilterList->begin(),
				m_pFilterList->end(),
				FilterTitleMatch( rTitle )
			);

    return bRet;
}

//------------------------------------------------------------------------------------
sal_Bool SvtFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters )
{
    sal_Bool bRet = sal_False;

	if ( m_pFilterList )
	{
		const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray();
		const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength();
		for ( ; pStart != pEnd; ++pStart )
			if ( m_pFilterList->end() != ::std::find_if( m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch( pStart->First ) ) )
				break;

		bRet = pStart != pEnd;
	}

	return bRet;
}

//------------------------------------------------------------------------------------
void SvtFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter )
{
	if ( !m_pFilterList )
    {
		m_pFilterList = new FilterList;

        // set the first filter to the current filter
        if ( ! m_aCurrentFilter.getLength() )
            m_aCurrentFilter = _rInitialCurrentFilter;
    }
}

//------------------------------------------------------------------------------------
// class SvtFilePicker
//------------------------------------------------------------------------------------
SvtFilePicker::SvtFilePicker( const Reference < XMultiServiceFactory >& xFactory )
	:OCommonPicker( xFactory )
	,m_pFilterList		( NULL )
	,m_pElemList		( NULL )
	,m_bMultiSelection	( sal_False )
	,m_nServiceType		( TemplateDescription::FILEOPEN_SIMPLE )
{
}

SvtFilePicker::~SvtFilePicker()
{
	if ( m_pFilterList && !m_pFilterList->empty() )
		m_pFilterList->erase( m_pFilterList->begin(), m_pFilterList->end() );
	delete m_pFilterList;

	if ( m_pElemList && !m_pElemList->empty() )
		m_pElemList->erase( m_pElemList->begin(), m_pElemList->end() );
	delete m_pElemList;
}

//------------------------------------------------------------------------------------
sal_Int16 SvtFilePicker::implExecutePicker( )
{
	getDialog()->SetFileCallback( this );

    prepareExecute();

    getDialog()->EnableAutocompletion( sal_True );
    // now we are ready to execute the dialog
    sal_Int16 nRet = getDialog()->Execute();

	// the execution of the dialog yields, so it is possible the at this point the window or the dialog is closed
	if ( getDialog() )
		getDialog()->SetFileCallback( NULL );

	return nRet;
}

//------------------------------------------------------------------------------------
SvtFileDialog* SvtFilePicker::implCreateDialog( Window* _pParent )
{
	WinBits	nExtraBits;
	WinBits	nBits = getWinBits( nExtraBits );

	SvtFileDialog* dialog = new SvtFileDialog( _pParent, nBits, nExtraBits );

	// Set StandardDir if present
	if ( m_aStandardDir.getLength() > 0)
	{
		String sStandardDir = String( m_aStandardDir );
		dialog->SetStandardDir( sStandardDir );
		dialog->SetBlackList( m_aBlackList );
	}

	return dialog;
}

//------------------------------------------------------------------------------------
// disambiguate XInterface
//------------------------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base )

//------------------------------------------------------------------------------------
// disambiguate XTypeProvider
//------------------------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvtFilePicker, OCommonPicker, SvtFilePicker_Base )

//------------------------------------------------------------------------------------
// XExecutableDialog functions
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException)
{
	OCommonPicker::setTitle( _rTitle );
}

//------------------------------------------------------------------------------------
sal_Int16 SAL_CALL SvtFilePicker::execute(  ) throw (RuntimeException)
{
	return OCommonPicker::execute();
}

//------------------------------------------------------------------------------------
// XAsynchronousExecutableDialog functions
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::setDialogTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException)
{
    setTitle( _rTitle );
}

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::startExecuteModal( const Reference< ::com::sun::star::ui::dialogs::XDialogClosedListener >& xListener ) throw (RuntimeException)
{
    m_xDlgClosedListener = xListener;
    prepareDialog();
    prepareExecute();
    getDialog()->EnableAutocompletion( sal_True );
    getDialog()->StartExecuteModal( LINK( this, SvtFilePicker, DialogClosedHdl ) );
}

//------------------------------------------------------------------------------------
// XFilePicker functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	m_bMultiSelection = bMode;
}

void SAL_CALL SvtFilePicker::setDefaultName( const rtl::OUString& aName ) throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	m_aDefaultName = aName;
}

void SAL_CALL SvtFilePicker::setDisplayDirectory( const rtl::OUString& aDirectory )
    throw( IllegalArgumentException, RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	m_aDisplayDirectory = aDirectory;
}

rtl::OUString SAL_CALL SvtFilePicker::getDisplayDirectory() throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	if ( getDialog() )
    {
        rtl::OUString aPath = getDialog()->GetPath();

		// #97148# ----
		if( m_aOldHideDirectory == aPath )
			return m_aOldDisplayDirectory;
		m_aOldHideDirectory = aPath;

		// #102204# -----
		if( !getDialog()->ContentIsFolder( aPath ) )
        {
            INetURLObject aFolder( aPath );
            aFolder.CutLastName();
            aPath = aFolder.GetMainURL( INetURLObject::NO_DECODE );
        }
		m_aOldDisplayDirectory = aPath;
        return aPath;
    }
    else
        return m_aDisplayDirectory;
}

Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getFiles() throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	if ( ! getDialog() )
	{
		Sequence< rtl::OUString > aEmpty;
		return aEmpty;
	}

	// if there is more than one path we have to return the path to the
	// files first and then the list of the selected entries

	SvStringsDtor* pPathList = getDialog()->GetPathList();
	sal_uInt16 i, nCount = pPathList->Count();
	sal_uInt16 nTotal = nCount > 1 ? nCount+1: nCount;

	Sequence< rtl::OUString > aPath( nTotal );

	if ( nCount == 1 )
		aPath[0] = rtl::OUString( *pPathList->GetObject( 0 ) );
	else if ( nCount > 1 )
	{
		INetURLObject aObj( *pPathList->GetObject( 0 ) );
		aObj.removeSegment();
		aPath[0] = aObj.GetMainURL( INetURLObject::NO_DECODE );

		for ( i = 0; i < nCount; /* i++ is done below */ )
		{
			aObj.SetURL( *pPathList->GetObject(i++) );
			aPath[i] = aObj.getName();
		}
	}

	delete pPathList;
	return aPath;
}

//------------------------------------------------------------------------------------
// XFilePickerControlAccess functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::setValue( sal_Int16 nElementID,
                                       sal_Int16 nControlAction,
                                       const Any& rValue )
    throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	if ( getDialog() )
	{
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
		aAccess.setValue( nElementID, nControlAction, rValue );
	}
	else
	{
		if ( !m_pElemList )
			m_pElemList = new ElementList;

        sal_Bool bFound = sal_False;
		ElementList::iterator aListIter;

        for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( ( rEntry.m_nElementID == nElementID ) &&
                 ( !rEntry.m_bHasValue || ( rEntry.m_nControlAction == nControlAction ) ) )
            {
                rEntry.setAction( nControlAction );
                rEntry.setValue( rValue );
                bFound = sal_True;
            }
		}

        if ( !bFound )
        {
            ElementEntry_Impl aNew( nElementID );
            aNew.setAction( nControlAction );
            aNew.setValue( rValue );
            m_pElemList->insert( m_pElemList->end(), aNew );
        }
	}
}

//------------------------------------------------------------------------------------

Any SAL_CALL SvtFilePicker::getValue( sal_Int16 nElementID, sal_Int16 nControlAction )
    throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	Any      aAny;

	// execute() called?
	if ( getDialog() )
	{
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
		aAny = aAccess.getValue( nElementID, nControlAction );
	}
    else if ( m_pElemList && !m_pElemList->empty() )
    {
		ElementList::iterator aListIter;
		for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( ( rEntry.m_nElementID == nElementID ) &&
                 ( rEntry.m_bHasValue ) &&
                 ( rEntry.m_nControlAction == nControlAction ) )
            {
                aAny = rEntry.m_aValue;
                break;
            }
		}
    }

    return aAny;
}


//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::setLabel( sal_Int16 nLabelID, const rtl::OUString& rValue )
    throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	if ( getDialog() )
	{
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
		aAccess.setLabel( nLabelID, rValue );
	}
	else
	{
		if ( !m_pElemList )
			m_pElemList = new ElementList;

        sal_Bool bFound = sal_False;
		ElementList::iterator aListIter;

        for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( rEntry.m_nElementID == nLabelID )
            {
                rEntry.setLabel( rValue );
                bFound = sal_True;
            }
		}

        if ( !bFound )
        {
            ElementEntry_Impl aNew( nLabelID );
            aNew.setLabel( rValue );
            m_pElemList->insert( m_pElemList->end(), aNew );
        }
	}
}

//------------------------------------------------------------------------------------
rtl::OUString SAL_CALL SvtFilePicker::getLabel( sal_Int16 nLabelID )
    throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	rtl::OUString aLabel;

    if ( getDialog() )
	{
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
		aLabel = aAccess.getLabel( nLabelID );
	}
    else if ( m_pElemList && !m_pElemList->empty() )
    {
		ElementList::iterator aListIter;
		for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( rEntry.m_nElementID == nLabelID )
            {
                if ( rEntry.m_bHasLabel )
                    aLabel = rEntry.m_aLabel;
                break;
            }
		}
    }

	return aLabel;
}

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::enableControl( sal_Int16 nElementID, sal_Bool bEnable )
    throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    if ( getDialog() )
	{
		::svt::OControlAccess aAccess( getDialog(), getDialog()->GetView() );
		aAccess.enableControl( nElementID, bEnable );
	}
    else
    {
		if ( !m_pElemList )
			m_pElemList = new ElementList;

        sal_Bool bFound = sal_False;
		ElementList::iterator aListIter;

        for ( aListIter = m_pElemList->begin();
			  aListIter != m_pElemList->end(); ++aListIter )
		{
			ElementEntry_Impl& rEntry = *aListIter;
            if ( rEntry.m_nElementID == nElementID )
            {
                rEntry.setEnabled( bEnable );
                bFound = sal_True;
            }
		}

        if ( !bFound )
        {
            ElementEntry_Impl aNew( nElementID );
            aNew.setEnabled( bEnable );
            m_pElemList->insert( m_pElemList->end(), aNew );
        }
    }
}

//------------------------------------------------------------------------------------
// XFilePickerNotifier functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::addFilePickerListener( const Reference< XFilePickerListener >& xListener ) throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	m_xListener = xListener;
}

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::removeFilePickerListener( const Reference< XFilePickerListener >& ) throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	m_xListener.clear();
}

//------------------------------------------------------------------------------------
// XFilePreview functions
//------------------------------------------------------------------------------------

Sequence< sal_Int16 > SAL_CALL SvtFilePicker::getSupportedImageFormats()
    throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    Sequence< sal_Int16 > aFormats( 1 );

    aFormats[0] = FilePreviewImageFormats::BITMAP;

    return aFormats;
}

//------------------------------------------------------------------------------------
sal_Int32 SAL_CALL SvtFilePicker::getTargetColorDepth() throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    sal_Int32 nDepth = 0;

    if ( getDialog() )
        nDepth = getDialog()->getTargetColorDepth();

    return nDepth;
}

//------------------------------------------------------------------------------------
sal_Int32 SAL_CALL SvtFilePicker::getAvailableWidth() throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    sal_Int32 nWidth = 0;

    if ( getDialog() )
        nWidth = getDialog()->getAvailableWidth();

    return nWidth;
}

//------------------------------------------------------------------------------------
sal_Int32 SAL_CALL SvtFilePicker::getAvailableHeight() throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    sal_Int32 nHeigth = 0;

    if ( getDialog() )
        nHeigth = getDialog()->getAvailableHeight();

    return nHeigth;
}

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::setImage( sal_Int16 aImageFormat, const Any& rImage )
    throw ( IllegalArgumentException, RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    if ( getDialog() )
        getDialog()->setImage( aImageFormat, rImage );
}

//------------------------------------------------------------------------------------
sal_Bool SAL_CALL SvtFilePicker::setShowState( sal_Bool bShowState )
    throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    sal_Bool bRet = sal_False;

    if ( getDialog() )
        bRet = getDialog()->setShowState( bShowState );

    return bRet;
}

//------------------------------------------------------------------------------------
sal_Bool SAL_CALL SvtFilePicker::getShowState() throw ( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    sal_Bool bRet = sal_False;

    if ( getDialog() )
        bRet = getDialog()->getShowState();

    return bRet;
}

//------------------------------------------------------------------------------------
// XFilterGroupManager functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::appendFilterGroup(	const ::rtl::OUString& sGroupTitle,
												const Sequence< StringPair >& aFilters )
	throw ( IllegalArgumentException, RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );

	// check the names
	if ( FilterNameExists( aFilters ) )
        throw IllegalArgumentException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("filter name exists")),
            static_cast< OWeakObject * >(this), 1);

	// ensure that we have a filter list
	::rtl::OUString sInitialCurrentFilter;
	if ( aFilters.getLength() )
		sInitialCurrentFilter = aFilters[0].First;
	ensureFilterList( sInitialCurrentFilter );

	// append the filter
	m_pFilterList->insert( m_pFilterList->end(), FilterEntry( sGroupTitle, aFilters ) );
}

//------------------------------------------------------------------------------------
// XFilterManager functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::appendFilter( const rtl::OUString& aTitle,
                                           const rtl::OUString& aFilter )
    throw( IllegalArgumentException, RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	// check the name
	if ( FilterNameExists( aTitle ) )
		// TODO: a more precise exception message
        throw IllegalArgumentException();

	// ensure that we have a filter list
	ensureFilterList( aTitle );

	// append the filter
	m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) );
}

//------------------------------------------------------------------------------------
void SAL_CALL SvtFilePicker::setCurrentFilter( const rtl::OUString& aTitle )
    throw( IllegalArgumentException, RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
    if ( ! FilterNameExists( aTitle ) )
        throw IllegalArgumentException();

	m_aCurrentFilter = aTitle;

    if ( getDialog() )
        getDialog()->SetCurFilter( aTitle );
}

//------------------------------------------------------------------------------------
rtl::OUString SAL_CALL SvtFilePicker::getCurrentFilter()
    throw( RuntimeException )
{
	checkAlive();

    ::vos::OGuard aGuard( Application::GetSolarMutex() );
	rtl::OUString aFilter = getDialog() ? rtl::OUString( getDialog()->GetCurFilter() ) :
                                            rtl::OUString( m_aCurrentFilter );
	return aFilter;
}


//------------------------------------------------------------------------------------
// XInitialization functions
//------------------------------------------------------------------------------------

void SAL_CALL SvtFilePicker::initialize( const Sequence< Any >& _rArguments )
	throw ( Exception, RuntimeException )
{
	checkAlive();

	Sequence< Any > aArguments( _rArguments.getLength());

	m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE;

	if ( _rArguments.getLength() >= 1 )
	{
		// compatibility: one argument, type sal_Int16 , specifies the service type
		int index = 0;

		if (_rArguments[0] >>= m_nServiceType)
		{
			// skip the first entry if it was the ServiceType, because it's not needed in OCommonPicker::initialize and it's not a NamedValue
			NamedValue emptyNamedValue;
			aArguments[0] <<= emptyNamedValue;
			index = 1;

		}
		for ( int i = index; i < _rArguments.getLength(); i++)
		{
			NamedValue namedValue;
			aArguments[i] <<= _rArguments[i];

			if (aArguments[i] >>= namedValue )
			{

				if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ) ) )
				{
					::rtl::OUString sStandardDir;

					namedValue.Value >>= sStandardDir;

					// Set the directory for the "back to the default dir" button
						if ( sStandardDir.getLength() > 0 )
					{
						m_aStandardDir = sStandardDir;
					}
				}
				else if ( namedValue.Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ) ) )
				{
					namedValue.Value >>= m_aBlackList;
				}
			}
		}
	}

	// let the base class analyze the sequence (will call into implHandleInitializationArgument)
	OCommonPicker::initialize( aArguments );
}

//-------------------------------------------------------------------------
sal_Bool SvtFilePicker::implHandleInitializationArgument( const ::rtl::OUString& _rName, const Any& _rValue ) SAL_THROW( ( Exception, RuntimeException ) )
{
	if ( _rName.equalsAscii( "TemplateDescription" ) )
	{
		m_nServiceType = TemplateDescription::FILEOPEN_SIMPLE;
		OSL_VERIFY( _rValue >>= m_nServiceType );
		return sal_True;
	}
	if ( _rName.equalsAscii( "StandardDir" ) )
	{
		OSL_VERIFY( _rValue >>= m_aStandardDir );
		return sal_True;
	}

	if ( _rName.equalsAscii( "BlackList" ) )
	{
		OSL_VERIFY( _rValue >>= m_aBlackList );
		return sal_True;
	}



	return OCommonPicker::implHandleInitializationArgument( _rName, _rValue );
}

//------------------------------------------------------------------------------------
// XServiceInfo
//------------------------------------------------------------------------------------

/* XServiceInfo */
rtl::OUString SAL_CALL SvtFilePicker::getImplementationName() throw( RuntimeException )
{
	return impl_getStaticImplementationName();
}

/* XServiceInfo */
sal_Bool SAL_CALL SvtFilePicker::supportsService( const rtl::OUString& sServiceName ) throw( RuntimeException )
{
    Sequence< rtl::OUString > seqServiceNames = getSupportedServiceNames();
    const rtl::OUString* pArray = seqServiceNames.getConstArray();
    for ( sal_Int32 i = 0; i < seqServiceNames.getLength(); i++ )
	{
        if ( sServiceName == pArray[i] )
		{
            return sal_True ;
		}
	}
    return sal_False ;
}

/* XServiceInfo */
Sequence< rtl::OUString > SAL_CALL SvtFilePicker::getSupportedServiceNames() throw( RuntimeException )
{
	return impl_getStaticSupportedServiceNames();
}

/* Helper for XServiceInfo */
Sequence< rtl::OUString > SvtFilePicker::impl_getStaticSupportedServiceNames()
{
    Sequence< rtl::OUString > seqServiceNames( 1 );
    rtl::OUString* pArray = seqServiceNames.getArray();
    pArray[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.OfficeFilePicker" );
    return seqServiceNames ;
}

/* Helper for XServiceInfo */
rtl::OUString SvtFilePicker::impl_getStaticImplementationName()
{
    return rtl::OUString::createFromAscii( "com.sun.star.svtools.OfficeFilePicker" );
}

/* Helper for registry */
Reference< XInterface > SAL_CALL SvtFilePicker::impl_createInstance(
	const Reference< XComponentContext >& rxContext) throw( Exception )
{
	Reference< XMultiServiceFactory > xServiceManager (rxContext->getServiceManager(), UNO_QUERY_THROW);
	return Reference< XInterface >( *new SvtFilePicker( xServiceManager ) );
}