/**************************************************************
 *
 * 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( sal_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, sal_True, sal_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( sal_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 ? sal_True : sal_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_uInt16 i = ENTRANCE; i <= MOTIONPATH; i++ )
		{
			if( mpTabPages[i]->select( rsPresetId ) )
			{
				mpTabControl->SetCurPageId( 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() ) );
}

}
