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

#ifndef _COM_SUN_STAR_UTIL_XCOLLATOR_HPP_
#include <com/sun/star/i18n/XCollator.hpp>
#endif

#ifndef _UNOTOOLS_PROCESSFACTORY_HXX
#include <comphelper/processfactory.hxx>
#endif
#include <vcl/svapp.hxx>
#include <vcl/tabctrl.hxx>
#include <vcl/tabpage.hxx>

#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#include <vcl/fixed.hxx>
#include <vcl/lstbox.hxx>
#include <vcl/combobox.hxx>
#include <svtools/valueset.hxx>

#include <svx/svdetc.hxx>
#include <svx/svdstr.hrc>
#include "sdresid.hxx"
#include <unotools/viewoptions.hxx>
#include <com/sun/star/presentation/EffectNodeType.hpp>
#include "CustomAnimationCreateDialog.hxx"
#ifndef _SD_CUSTOMANIMATIONCREATEDIALOG_HRC
#include "CustomAnimationCreateDialog.hrc"
#endif
#ifndef _SD_CUSTOMANIMATION_HRC
#include "CustomAnimation.hrc"
#endif
#include "CustomAnimationPane.hxx"
#include "optsitem.hxx"
#include "sddll.hxx"

#include "helpids.h"

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

using ::rtl::OUString;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;

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

namespace sd {


const int ENTRANCE = 0;
const int EMPHASIS = 1;
const int EXIT = 2;
const int MOTIONPATH = 3;
const int MISCEFFECTS = 4;

extern void fillDurationComboBox( ComboBox* pBox );

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

class CategoryListBox : public ListBox
{
public:
	CategoryListBox( Window* pParent, const ResId& rResId );
	~CategoryListBox();

	virtual void        MouseButtonUp( const MouseEvent& rMEvt );

	sal_uInt16			InsertCategory( const XubString& rStr, sal_uInt16 nPos = LISTBOX_APPEND );

	void			SetDoubleClickLink( const Link& rDoubleClickHdl ) { maDoubleClickHdl = rDoubleClickHdl; }

	DECL_LINK( implDoubleClickHdl, Control* );

private:
	virtual void	UserDraw( const UserDrawEvent& rUDEvt );

	Link			maDoubleClickHdl;
};

CategoryListBox::CategoryListBox( Window* pParent, const ResId& rResId )
: ListBox( pParent, rResId )
{
	EnableUserDraw( true );
	SetDoubleClickHdl( LINK( this, CategoryListBox, implDoubleClickHdl ) );
}

CategoryListBox::~CategoryListBox()
{
}

sal_uInt16 CategoryListBox::InsertCategory( const XubString& rStr, sal_uInt16 nPos /* = LISTBOX_APPEND */ )
{
	sal_uInt16 n = ListBox::InsertEntry( rStr, nPos );
	if( n != LISTBOX_ENTRY_NOTFOUND )
		ListBox::SetEntryFlags( n, ListBox::GetEntryFlags(n) | LISTBOX_ENTRY_FLAG_DISABLE_SELECTION );

	return n;
}

void CategoryListBox::UserDraw( const UserDrawEvent& rUDEvt )
{
	const sal_uInt16 nItem = rUDEvt.GetItemId();

	if( ListBox::GetEntryFlags(nItem) & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION )
	{
		Rectangle aOutRect( rUDEvt.GetRect() );
		OutputDevice* pDev = rUDEvt.GetDevice();

		// fill the background
        Color aColor (GetSettings().GetStyleSettings().GetDialogColor());

        pDev->SetFillColor (aColor);
        pDev->SetLineColor ();
        pDev->DrawRect(aOutRect);

        // Erase the four corner pixels to make the rectangle appear rounded.
        pDev->SetLineColor( GetSettings().GetStyleSettings().GetWindowColor());
        pDev->DrawPixel( aOutRect.TopLeft());
        pDev->DrawPixel( Point(aOutRect.Right(), aOutRect.Top()));
        pDev->DrawPixel( Point(aOutRect.Left(), aOutRect.Bottom()));
        pDev->DrawPixel( Point(aOutRect.Right(), aOutRect.Bottom()));

		// draw the category title
		pDev->DrawText (aOutRect, GetEntry(nItem), TEXT_DRAW_CENTER );
	}
	else
	{
		DrawEntry( rUDEvt, true, true );
	}
}

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

IMPL_LINK( CategoryListBox, implDoubleClickHdl, Control*, EMPTYARG )
{
	CaptureMouse();
	return 0;
}

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

void CategoryListBox::MouseButtonUp( const MouseEvent& rMEvt )
{
    ReleaseMouse();
	if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
	{
		if( maDoubleClickHdl.IsSet() )
			maDoubleClickHdl.Call( this );
	}
	else
	{
		ListBox::MouseButtonUp( rMEvt );
	}
}

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

class CustomAnimationCreateTabPage : public TabPage
{
public:
	CustomAnimationCreateTabPage( Window* pParent, CustomAnimationCreateDialog* pDialogParent, int nTabId, const PresetCategoryList& rCategoryList, bool bHasText );
	~CustomAnimationCreateTabPage();

	PathKind getCreatePathKind() const;
	CustomAnimationPresetPtr getSelectedPreset() const;
	double getDuration() const;
	void setDuration( double fDuration );

	bool getIsPreview() const;
	void setIsPreview( bool bIsPreview );

	bool select( const OUString& rsPresetId );

private:
	DECL_LINK( implSelectHdl, Control* );
	DECL_LINK( implDoubleClickHdl, Control* );

	void onSelectEffect();

	void clearEffects();

private:
	CategoryListBox*	mpLBEffects;
	FixedText*	mpFTSpeed;
	ComboBox*	mpCBSpeed;
	CheckBox*	mpCBXPReview;

	CustomAnimationCreateDialog*		mpParent;

	sal_uInt16 mnCurvePathPos;
	sal_uInt16 mnPolygonPathPos;
	sal_uInt16 mnFreeformPathPos;

};

struct ImplStlEffectCategorySortHelper
{
	ImplStlEffectCategorySortHelper();
	bool operator()( const CustomAnimationPresetPtr& p1, const CustomAnimationPresetPtr& p2 );

private:
	uno::Reference< i18n::XCollator > mxCollator;
};

ImplStlEffectCategorySortHelper::ImplStlEffectCategorySortHelper()
{
	uno::Reference<lang::XMultiServiceFactory> xFac( ::comphelper::getProcessServiceFactory() );
	if( xFac.is() )
	{
		mxCollator.set( xFac->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ) ), uno::UNO_QUERY );

		if( mxCollator.is() )
		{
			const lang::Locale& rLocale = Application::GetSettings().GetLocale();
			mxCollator->loadDefaultCollator(rLocale, 0);
		}
	}
}

bool ImplStlEffectCategorySortHelper::operator()( const CustomAnimationPresetPtr& p1, const CustomAnimationPresetPtr& p2 )
{
	return mxCollator.is() ? mxCollator->compareString(p1->getLabel(), p2->getLabel()) == -1 : false;
}

CustomAnimationCreateTabPage::CustomAnimationCreateTabPage( Window* pParent, CustomAnimationCreateDialog* pDialogParent, int nTabId, const PresetCategoryList& rCategoryList, bool bHasText )
: TabPage( pParent, SdResId( RID_TP_CUSTOMANIMATION_ENTRANCE ) )
, mpParent( pDialogParent )
, mnCurvePathPos( LISTBOX_ENTRY_NOTFOUND )
, mnPolygonPathPos( LISTBOX_ENTRY_NOTFOUND )
, mnFreeformPathPos( LISTBOX_ENTRY_NOTFOUND )
{
	mpLBEffects = new CategoryListBox( this, SdResId( LB_EFFECTS ) );
	mpFTSpeed = new FixedText( this, SdResId( FT_SPEED ) );
	mpCBSpeed = new ComboBox( this, SdResId( CB_SPEED ) );
	mpCBXPReview = new CheckBox( this, SdResId( CBX_PREVIEW ) );

	String sMotionPathLabel( SdResId( STR_USERPATH ) );

	FreeResource();

	sal_uInt16 nFirstEffect = LISTBOX_ENTRY_NOTFOUND;

	if( nTabId == MOTIONPATH )
	{
		mpLBEffects->InsertCategory( sMotionPathLabel );

		mnCurvePathPos = nFirstEffect = mpLBEffects->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulCOMBLINE) );
		mnPolygonPathPos = mpLBEffects->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulPOLY) );
		mnFreeformPathPos = mpLBEffects->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulFREELINE) );
	};

	PresetCategoryList::const_iterator aCategoryIter( rCategoryList.begin() );
	const PresetCategoryList::const_iterator aCategoryEnd( rCategoryList.end() );
	while( aCategoryIter != aCategoryEnd )
	{
		PresetCategoryPtr pCategory( *aCategoryIter++ );
		if( pCategory.get() )
		{
			mpLBEffects->InsertCategory( pCategory->maLabel );

			std::vector< CustomAnimationPresetPtr > aSortedVector(pCategory->maEffects.size());
			std::copy( pCategory->maEffects.begin(), pCategory->maEffects.end(), aSortedVector.begin() );
			ImplStlEffectCategorySortHelper aSortHelper;
			std::sort( aSortedVector.begin(), aSortedVector.end(), aSortHelper );

			std::vector< CustomAnimationPresetPtr >::const_iterator aIter( aSortedVector.begin() );
			const std::vector< CustomAnimationPresetPtr >::const_iterator aEnd( aSortedVector.end() );
			while( aIter != aEnd )
			{
				CustomAnimationPresetPtr pDescriptor = (*aIter++);
				if( pDescriptor.get() && (bHasText || !pDescriptor->isTextOnly() ) )
				{
					sal_uInt16 nPos = mpLBEffects->InsertEntry( pDescriptor->getLabel() );
					mpLBEffects->SetEntryData( nPos, static_cast<void*>( new CustomAnimationPresetPtr( pDescriptor ) ) );

					if( nFirstEffect == LISTBOX_ENTRY_NOTFOUND )
						nFirstEffect = nPos;
				}
			}
		}
	}

	mpLBEffects->SelectEntryPos( nFirstEffect );

	fillDurationComboBox( mpCBSpeed );

	if( nFirstEffect != LISTBOX_ENTRY_NOTFOUND )
		onSelectEffect();

	mpLBEffects->SetSelectHdl( LINK( this, CustomAnimationCreateTabPage, implSelectHdl ) );
	mpLBEffects->SetDoubleClickLink( LINK( this, CustomAnimationCreateTabPage, implDoubleClickHdl ) );
}

CustomAnimationCreateTabPage::~CustomAnimationCreateTabPage()
{
	clearEffects();

	delete mpLBEffects;
	delete mpFTSpeed;
	delete mpCBSpeed;
	delete mpCBXPReview;
}

IMPL_LINK( CustomAnimationCreateTabPage, implSelectHdl, Control*, pControl )
{
	if( pControl == mpLBEffects )
		onSelectEffect();
	return 0;
}

IMPL_LINK( CustomAnimationCreateTabPage, implDoubleClickHdl, Control*, pControl )
{
	if( pControl == mpLBEffects )
	{
		if( mpLBEffects->GetSelectEntryCount() )
			mpParent->EndDialog( true );
	}
	return 0;
}

void CustomAnimationCreateTabPage::onSelectEffect()
{
	CustomAnimationPresetPtr*p = static_cast< CustomAnimationPresetPtr* >( mpLBEffects->GetEntryData( mpLBEffects->GetSelectEntryPos() ) );

	if( !p )
		return;

	CustomAnimationPresetPtr pPreset( *p );

	const double fDuration = pPreset->getDuration();
	sal_uInt16 nPos = 0xffff;

	if( fDuration == 5.0 )
		nPos = 0;
	else if( fDuration == 3.0 )
		nPos = 1;
	else if( fDuration == 2.0 )
		nPos = 2;
	else if( fDuration == 1.0 )
		nPos = 3;
	else if( fDuration == 0.5 )
		nPos = 4;

	mpCBSpeed->SelectEntryPos( nPos );

    bool bHasSpeed = pPreset->getDuration() > 0.001;
    mpCBSpeed->Enable( bHasSpeed );
    mpFTSpeed->Enable( bHasSpeed );

	if( mpCBXPReview->IsChecked() )
	{
		mpParent->preview( pPreset );
	}
}

void CustomAnimationCreateTabPage::clearEffects()
{
	sal_uInt16 nPos = mpLBEffects->GetEntryCount();
	while( nPos-- )
		delete static_cast< CustomAnimationPresetPtr* >( mpLBEffects->GetEntryData( nPos ) );

	mpLBEffects->Clear();
}

CustomAnimationPresetPtr CustomAnimationCreateTabPage::getSelectedPreset() const
{
	CustomAnimationPresetPtr pPreset;

	if( mpLBEffects->GetSelectEntryCount() == 1 )
	{
		void* pEntryData = mpLBEffects->GetEntryData( mpLBEffects->GetSelectEntryPos() );
		if( pEntryData )
			pPreset = *static_cast< CustomAnimationPresetPtr* >( pEntryData );
	}

	return pPreset;
}

PathKind CustomAnimationCreateTabPage::getCreatePathKind() const
{
	PathKind eKind = NONE;

	if( mpLBEffects->GetSelectEntryCount() == 1 )
	{
		const sal_uInt16 nPos = mpLBEffects->GetSelectEntryPos();
		if( nPos == mnCurvePathPos )
		{
			eKind = CURVE;
		}
		else if( nPos == mnPolygonPathPos )
		{
			eKind = POLYGON;
		}
		else if( nPos == mnFreeformPathPos )
		{
			eKind = FREEFORM;
		}
	}

	return eKind;
}



double CustomAnimationCreateTabPage::getDuration() const
{
	sal_uInt16 nPos = mpCBSpeed->GetSelectEntryPos();
	if( (nPos == 0xffff) || !mpCBSpeed->IsEnabled() )
	{
		CustomAnimationPresetPtr pPreset = getSelectedPreset();
		if( pPreset.get() )
			return pPreset->getDuration();
	}

	switch( nPos )
	{
	case 0: return 5.0f;
	case 1: return 3.0f;
	case 2: return 2.0f;
	case 3: return 1.0f;
	case 4: return 0.5f;
	}

	return 0.0f;
}

void CustomAnimationCreateTabPage::setDuration( double fDuration )
{
	sal_uInt16 nPos = 0;
	if( fDuration < 2.0f )
	{
		if( fDuration < 1.0f )
		{
			nPos = 4;
		}
		else
		{
			nPos = 3;
		}
	}
	else if( fDuration < 5.0f )
	{
		if( fDuration < 3.0f )
		{
			nPos = 2;
		}
		else
		{
			nPos = 1;
		}
	}

	mpCBSpeed->SelectEntryPos( nPos );
}

bool CustomAnimationCreateTabPage::getIsPreview() const
{
	return mpCBXPReview->IsChecked() ? true : false;
}

void CustomAnimationCreateTabPage::setIsPreview( bool bIsPreview )
{
	mpCBXPReview->Check( bIsPreview ? true : false );
}

bool CustomAnimationCreateTabPage::select( const OUString& rsPresetId )
{
	sal_uInt16 nPos = mpLBEffects->GetEntryCount();
	while( nPos-- )
	{
		void* pEntryData = mpLBEffects->GetEntryData( nPos );
		if( pEntryData )
		{
			CustomAnimationPresetPtr& pPtr = *static_cast< CustomAnimationPresetPtr* >(pEntryData);
			if( pPtr.get() && pPtr->getPresetId() == rsPresetId )
			{
				mpLBEffects->SelectEntryPos( nPos );
				return true;
			}
		}
	}

	return false;
}

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

CustomAnimationCreateDialog::CustomAnimationCreateDialog( Window* pParent, CustomAnimationPane* pPane, const std::vector< ::com::sun::star::uno::Any >& rTargets, bool bHasText, const ::rtl::OUString& rsPresetId, double fDuration  )
:	TabDialog( pParent, SdResId( DLG_CUSTOMANIMATION_CREATE ) )
,	mpPane( pPane )
,	mrTargets( rTargets )
,	mfDuration( fDuration )
{
	mpTabControl = new TabControl( this, SdResId( 1 ) );
	mpOKButton = new OKButton(this, SdResId( 1 ) ) ;
	mpCancelButton = new CancelButton(this, SdResId( 1 ) );
	mpHelpButton = new HelpButton(this, SdResId( 1 ) );

	FreeResource();

	SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
	mbIsPreview = pOptions->IsPreviewNewEffects();

	const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
	mpTabPages[ENTRANCE] = new CustomAnimationCreateTabPage( mpTabControl, this, ENTRANCE, rPresets.getEntrancePresets(), bHasText );
    mpTabPages[ENTRANCE]->SetHelpId( HID_SD_CUSTOMANIMATIONDIALOG_ENTRANCE );
	mpTabControl->SetTabPage( RID_TP_CUSTOMANIMATION_ENTRANCE, mpTabPages[ENTRANCE] );
	mpTabPages[EMPHASIS] = new CustomAnimationCreateTabPage( mpTabControl, this, EMPHASIS, rPresets.getEmphasisPresets(), bHasText );
    mpTabPages[EMPHASIS]->SetHelpId( HID_SD_CUSTOMANIMATIONDIALOG_EMPHASIS );
	mpTabControl->SetTabPage( RID_TP_CUSTOMANIMATION_EMPHASIS, mpTabPages[EMPHASIS] );
	mpTabPages[EXIT] = new CustomAnimationCreateTabPage( mpTabControl, this, EXIT, rPresets.getExitPresets(), bHasText );
    mpTabPages[EXIT]->SetHelpId( HID_SD_CUSTOMANIMATIONDIALOG_EXIT );
	mpTabControl->SetTabPage( RID_TP_CUSTOMANIMATION_EXIT, mpTabPages[EXIT] );
	mpTabPages[MOTIONPATH] = new CustomAnimationCreateTabPage( mpTabControl, this, MOTIONPATH, rPresets.getMotionPathsPresets(), bHasText );
    mpTabPages[MOTIONPATH]->SetHelpId( HID_SD_CUSTOMANIMATIONDIALOG_MOTIONPATH );
	mpTabControl->SetTabPage( RID_TP_CUSTOMANIMATION_MOTIONPATH, mpTabPages[MOTIONPATH] );
	mpTabPages[MISCEFFECTS] = new CustomAnimationCreateTabPage( mpTabControl, this, MISCEFFECTS, rPresets.getMiscPresets(), bHasText );
    mpTabPages[MISCEFFECTS]->SetHelpId( HID_SD_CUSTOMANIMATIONDIALOG_MISCEFFECTS );
	mpTabControl->SetTabPage( RID_TP_CUSTOMANIMATION_MISCEFFECTS, mpTabPages[MISCEFFECTS] );

	getCurrentPage()->setDuration( mfDuration );
	getCurrentPage()->setIsPreview( mbIsPreview );

    mpTabControl->SetActivatePageHdl( LINK( this, CustomAnimationCreateDialog, implActivatePagekHdl ) );
	mpTabControl->SetDeactivatePageHdl( LINK( this, CustomAnimationCreateDialog, implDeactivatePagekHdl ) );

    setPosition();

	// select current preset if available
	if( rsPresetId.getLength() != 0 )
	{
		for( sal_uInt32 i = ENTRANCE; i <= MOTIONPATH; i++ )
		{
			if( mpTabPages[i]->select( rsPresetId ) )
			{
				mpTabControl->SetCurPageId( static_cast< sal_uInt16 >(RID_TP_CUSTOMANIMATION_ENTRANCE + i ));
				break;
			}
		}
	}
}

CustomAnimationCreateDialog::~CustomAnimationCreateDialog()
{
    storePosition();

	SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
	pOptions->SetPreviewNewEffects( getCurrentPage()->getIsPreview() );

	delete mpTabPages[ENTRANCE];
	delete mpTabPages[EMPHASIS];
	delete mpTabPages[EXIT];
	delete mpTabPages[MOTIONPATH];
	delete mpTabPages[MISCEFFECTS];

	delete mpTabControl;
	delete mpOKButton;
	delete mpCancelButton;
	delete mpHelpButton;
}

CustomAnimationCreateTabPage* CustomAnimationCreateDialog::getCurrentPage() const
{
	switch( mpTabControl->GetCurPageId() )
	{
	case RID_TP_CUSTOMANIMATION_ENTRANCE:	return mpTabPages[ENTRANCE];
	case RID_TP_CUSTOMANIMATION_EMPHASIS:	return mpTabPages[EMPHASIS];
	case RID_TP_CUSTOMANIMATION_EXIT:		return mpTabPages[EXIT];
	case RID_TP_CUSTOMANIMATION_MISCEFFECTS:return mpTabPages[MISCEFFECTS];
	//case RID_TP_CUSTOMANIMATION_MOTIONPATH:
	default:
											return mpTabPages[MOTIONPATH];
	}
}

PathKind CustomAnimationCreateDialog::getCreatePathKind() const
{
	return getCurrentPage()->getCreatePathKind();
}

CustomAnimationPresetPtr CustomAnimationCreateDialog::getSelectedPreset() const
{
	return getCurrentPage()->getSelectedPreset();
}

double CustomAnimationCreateDialog::getSelectedDuration() const
{
	return getCurrentPage()->getDuration();
}

IMPL_LINK( CustomAnimationCreateDialog, implActivatePagekHdl, Control*, EMPTYARG )
{
	getCurrentPage()->setDuration( mfDuration );
	getCurrentPage()->setIsPreview( mbIsPreview );
	return 1;
}

IMPL_LINK( CustomAnimationCreateDialog, implDeactivatePagekHdl, Control*, EMPTYARG )
{
	mfDuration = getCurrentPage()->getDuration();
	mbIsPreview = getCurrentPage()->getIsPreview();
	return 1;
}

void CustomAnimationCreateDialog::preview( const CustomAnimationPresetPtr& pPreset ) const
{
	MainSequencePtr pSequence( new MainSequence() );

	std::vector< Any >::const_iterator aIter( mrTargets.begin() );
	const std::vector< Any >::const_iterator aEnd( mrTargets.end() );

	const double fDuration = getSelectedDuration();

	bool bFirst = true;
	while( aIter != aEnd )
	{
		CustomAnimationEffectPtr pNew(
			pSequence->append( pPreset, (*aIter++), fDuration ) );

		if( bFirst )
			bFirst = false;
		else
			pNew->setNodeType( EffectNodeType::WITH_PREVIOUS );
	}

	mpPane->preview( pSequence->getRootNode() );
}

namespace
{
Window * lcl_GetTopmostParent( Window * pWindow )
{
    Window * pResult = 0;
    Window * pCurrent = pWindow ? pWindow->GetParent() : 0;
    while( pCurrent )
    {
        pResult = pCurrent;
        pCurrent = pCurrent->GetParent();
    }
    return pResult;
}
}

void CustomAnimationCreateDialog::setPosition()
{
	SvtViewOptions aDlgOpt(
        E_TABDIALOG, String::CreateFromInt32( DLG_CUSTOMANIMATION_CREATE ) );
	if ( aDlgOpt.Exists() )
	{
		SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(),
                                    RTL_TEXTENCODING_ASCII_US ) );
    }
    else
    {
        // default position: aligned with right edge of parent
        Window * pParent = lcl_GetTopmostParent( this );
        if( pParent )
        {
            Point aPos( GetPosPixel());
            Size  aSize( GetSizePixel());
            Point aParentPos( pParent->GetPosPixel());
            Size  aParentSize( pParent->GetSizePixel());

            // right center
            aPos.setX( aParentSize.getWidth() - aSize.getWidth() );
            aPos.setY( (aParentSize.getHeight() - aSize.getHeight()) / 2 );
            SetPosPixel( aPos );
        }
    }
}

void CustomAnimationCreateDialog::storePosition()
{
    // save settings (screen position and current page)
	SvtViewOptions aDlgOpt(
        E_TABDIALOG, String::CreateFromInt32( DLG_CUSTOMANIMATION_CREATE ) );
	aDlgOpt.SetWindowState(
        OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) );
}

}
