1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/i18n/Collator.hpp>
22 #include <comphelper/processfactory.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/tabctrl.hxx>
25 #include <vcl/tabpage.hxx>
27 #include <vcl/builderfactory.hxx>
28 #include <vcl/button.hxx>
29 #include <vcl/fixed.hxx>
30 #include <vcl/lstbox.hxx>
31 #include <vcl/combobox.hxx>
32 #include <vcl/settings.hxx>
34 #include <svx/svdetc.hxx>
35 #include <svx/svdstr.hrc>
36 #include "sdresid.hxx"
37 #include <unotools/viewoptions.hxx>
38 #include <com/sun/star/presentation/EffectNodeType.hpp>
39 #include "CustomAnimationCreateDialog.hxx"
40 #include "CustomAnimation.hrc"
41 #include "CustomAnimationPane.hxx"
42 #include "optsitem.hxx"
48 using namespace ::com::sun::star
;
50 using ::com::sun::star::uno::UNO_QUERY
;
51 using ::com::sun::star::uno::UNO_QUERY_THROW
;
52 using ::com::sun::star::uno::Any
;
53 using ::com::sun::star::uno::Reference
;
54 using ::com::sun::star::uno::Exception
;
56 using namespace ::com::sun::star::presentation
;
60 const int ENTRANCE
= 0;
61 const int EMPHASIS
= 1;
63 const int MOTIONPATH
= 3;
64 const int MISCEFFECTS
= 4;
66 class CategoryListBox
: public ListBox
69 CategoryListBox( vcl::Window
* pParent
);
70 virtual ~CategoryListBox();
72 virtual void MouseButtonUp( const MouseEvent
& rMEvt
) SAL_OVERRIDE
;
74 sal_Int32
InsertCategory( const OUString
& rStr
, sal_Int32 nPos
= LISTBOX_APPEND
);
76 void SetDoubleClickLink( const Link
<>& rDoubleClickHdl
) { maDoubleClickHdl
= rDoubleClickHdl
; }
78 DECL_LINK(implDoubleClickHdl
, void *);
81 virtual void UserDraw( const UserDrawEvent
& rUDEvt
) SAL_OVERRIDE
;
83 Link
<> maDoubleClickHdl
;
86 CategoryListBox::CategoryListBox( vcl::Window
* pParent
)
87 : ListBox( pParent
, WB_TABSTOP
| WB_BORDER
)
89 EnableUserDraw( true );
90 SetDoubleClickHdl( LINK( this, CategoryListBox
, implDoubleClickHdl
) );
93 VCL_BUILDER_FACTORY(CategoryListBox
)
95 CategoryListBox::~CategoryListBox()
99 sal_Int32
CategoryListBox::InsertCategory( const OUString
& rStr
, sal_Int32 nPos
/* = LISTBOX_APPEND */ )
101 sal_Int32 n
= ListBox::InsertEntry( rStr
, nPos
);
102 if( n
!= LISTBOX_ENTRY_NOTFOUND
)
103 ListBox::SetEntryFlags( n
, ListBox::GetEntryFlags(n
) | ListBoxEntryFlags::DisableSelection
);
108 void CategoryListBox::UserDraw( const UserDrawEvent
& rUDEvt
)
110 const sal_uInt16 nItem
= rUDEvt
.GetItemId();
112 if( ListBox::GetEntryFlags(nItem
) & ListBoxEntryFlags::DisableSelection
)
114 Rectangle
aOutRect( rUDEvt
.GetRect() );
115 vcl::RenderContext
* pDev
= rUDEvt
.GetRenderContext();
117 // fill the background
118 Color
aColor (GetSettings().GetStyleSettings().GetDialogColor());
120 pDev
->SetFillColor (aColor
);
121 pDev
->SetLineColor ();
122 pDev
->DrawRect(aOutRect
);
124 // Erase the four corner pixels to make the rectangle appear rounded.
125 pDev
->SetLineColor( GetSettings().GetStyleSettings().GetWindowColor());
126 pDev
->DrawPixel( aOutRect
.TopLeft());
127 pDev
->DrawPixel( Point(aOutRect
.Right(), aOutRect
.Top()));
128 pDev
->DrawPixel( Point(aOutRect
.Left(), aOutRect
.Bottom()));
129 pDev
->DrawPixel( Point(aOutRect
.Right(), aOutRect
.Bottom()));
131 // draw the category title
132 pDev
->DrawText (aOutRect
, GetEntry(nItem
), DrawTextFlags::Center
);
136 DrawEntry( rUDEvt
, true, true );
140 IMPL_LINK_NOARG(CategoryListBox
, implDoubleClickHdl
)
146 void CategoryListBox::MouseButtonUp( const MouseEvent
& rMEvt
)
149 if( rMEvt
.IsLeft() && (rMEvt
.GetClicks() == 2) )
151 if( maDoubleClickHdl
.IsSet() )
152 maDoubleClickHdl
.Call( this );
156 ListBox::MouseButtonUp( rMEvt
);
160 class CustomAnimationCreateTabPage
: public TabPage
163 CustomAnimationCreateTabPage( vcl::Window
* pParent
, CustomAnimationCreateDialog
* pDialogParent
, sal_uInt16 nTabId
, const PresetCategoryList
& rCategoryList
, bool bHasText
, bool bIsMotionPath
= false );
164 virtual ~CustomAnimationCreateTabPage();
165 virtual void dispose() SAL_OVERRIDE
;
167 PathKind
getCreatePathKind() const;
168 CustomAnimationPresetPtr
getSelectedPreset() const;
169 double getDuration() const;
170 void setDuration( double fDuration
);
172 bool getIsPreview() const;
173 void setIsPreview( bool bIsPreview
);
175 sal_uInt16
getId() const { return mnId
;}
177 bool select( const OUString
& rsPresetId
);
180 DECL_LINK( implSelectHdl
, Control
* );
181 DECL_LINK( implDoubleClickHdl
, Control
* );
183 void onSelectEffect();
188 VclPtr
<CategoryListBox
> mpLBEffects
;
189 VclPtr
<FixedText
> mpFTSpeed
;
190 VclPtr
<ListBox
> mpCBSpeed
;
191 VclPtr
<CheckBox
> mpCBXPReview
;
193 VclPtr
<CustomAnimationCreateDialog
> mpParent
;
197 sal_Int32 mnCurvePathPos
;
198 sal_Int32 mnPolygonPathPos
;
199 sal_Int32 mnFreeformPathPos
;
203 struct ImplStlEffectCategorySortHelper
205 ImplStlEffectCategorySortHelper();
206 bool operator()( const CustomAnimationPresetPtr
& p1
, const CustomAnimationPresetPtr
& p2
);
209 uno::Reference
< i18n::XCollator
> mxCollator
;
212 ImplStlEffectCategorySortHelper::ImplStlEffectCategorySortHelper()
214 mxCollator
= i18n::Collator::create( ::comphelper::getProcessComponentContext() );
216 const lang::Locale
& rLocale
= Application::GetSettings().GetLanguageTag().getLocale();
217 mxCollator
->loadDefaultCollator(rLocale
, 0);
220 bool ImplStlEffectCategorySortHelper::operator()( const CustomAnimationPresetPtr
& p1
, const CustomAnimationPresetPtr
& p2
)
222 return mxCollator
->compareString(p1
->getLabel(), p2
->getLabel()) == -1;
225 CustomAnimationCreateTabPage::CustomAnimationCreateTabPage( vcl::Window
* pParent
, CustomAnimationCreateDialog
* pDialogParent
, sal_uInt16 nTabId
, const PresetCategoryList
& rCategoryList
, bool bHasText
, bool bIsMotionPath
)
226 : TabPage( pParent
, "CustomAnimationCreateTab", "modules/simpress/ui/customanimationcreatetab.ui" )
227 , mpParent( pDialogParent
)
229 , mnCurvePathPos( LISTBOX_ENTRY_NOTFOUND
)
230 , mnPolygonPathPos( LISTBOX_ENTRY_NOTFOUND
)
231 , mnFreeformPathPos( LISTBOX_ENTRY_NOTFOUND
)
233 get( mpLBEffects
, "effect_list" );
234 mpLBEffects
->set_height_request( mpLBEffects
->GetTextHeight() * 16 );
236 get( mpFTSpeed
, "effect_speed_label" );
237 get( mpCBSpeed
, "effect_speed_list" );
238 get( mpCBXPReview
, "auto_preview" );
240 fillDurationComboBox(mpCBSpeed
);
242 OUString
sMotionPathLabel( SD_RESSTR( STR_CUSTOMANIMATION_USERPATH
) );
244 sal_Int32 nFirstEffect
= LISTBOX_ENTRY_NOTFOUND
;
248 mpLBEffects
->InsertCategory( sMotionPathLabel
);
250 mnCurvePathPos
= nFirstEffect
= mpLBEffects
->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulCOMBLINE
) );
251 mnPolygonPathPos
= mpLBEffects
->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulPOLY
) );
252 mnFreeformPathPos
= mpLBEffects
->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulFREELINE
) );
255 PresetCategoryList::const_iterator
aCategoryIter( rCategoryList
.begin() );
256 const PresetCategoryList::const_iterator
aCategoryEnd( rCategoryList
.end() );
257 while( aCategoryIter
!= aCategoryEnd
)
259 PresetCategoryPtr
pCategory( *aCategoryIter
++ );
260 if( pCategory
.get() )
262 mpLBEffects
->InsertCategory( pCategory
->maLabel
);
264 std::vector
< CustomAnimationPresetPtr
> aSortedVector(pCategory
->maEffects
.size());
265 std::copy( pCategory
->maEffects
.begin(), pCategory
->maEffects
.end(), aSortedVector
.begin() );
266 ImplStlEffectCategorySortHelper aSortHelper
;
267 std::sort( aSortedVector
.begin(), aSortedVector
.end(), aSortHelper
);
269 std::vector
< CustomAnimationPresetPtr
>::const_iterator
aIter( aSortedVector
.begin() );
270 const std::vector
< CustomAnimationPresetPtr
>::const_iterator
aEnd( aSortedVector
.end() );
271 while( aIter
!= aEnd
)
273 CustomAnimationPresetPtr pDescriptor
= (*aIter
++);
274 if( pDescriptor
.get() && (bHasText
|| !pDescriptor
->isTextOnly() ) )
276 sal_Int32 nPos
= mpLBEffects
->InsertEntry( pDescriptor
->getLabel() );
277 mpLBEffects
->SetEntryData( nPos
, static_cast<void*>( new CustomAnimationPresetPtr( pDescriptor
) ) );
279 if( nFirstEffect
== LISTBOX_ENTRY_NOTFOUND
)
286 mpLBEffects
->SelectEntryPos( nFirstEffect
);
288 if( nFirstEffect
!= LISTBOX_ENTRY_NOTFOUND
)
291 mpLBEffects
->SetSelectHdl( LINK( this, CustomAnimationCreateTabPage
, implSelectHdl
) );
292 mpLBEffects
->SetDoubleClickLink( LINK( this, CustomAnimationCreateTabPage
, implDoubleClickHdl
) );
295 CustomAnimationCreateTabPage::~CustomAnimationCreateTabPage()
300 void CustomAnimationCreateTabPage::dispose()
306 mpCBXPReview
.clear();
311 IMPL_LINK( CustomAnimationCreateTabPage
, implSelectHdl
, Control
*, pControl
)
313 if( pControl
== mpLBEffects
)
318 IMPL_LINK( CustomAnimationCreateTabPage
, implDoubleClickHdl
, Control
*, pControl
)
320 if( pControl
== mpLBEffects
)
322 if( mpLBEffects
->GetSelectEntryCount() )
323 mpParent
->EndDialog( RET_OK
);
328 void CustomAnimationCreateTabPage::onSelectEffect()
330 CustomAnimationPresetPtr
*p
= static_cast< CustomAnimationPresetPtr
* >( mpLBEffects
->GetSelectEntryData() );
335 CustomAnimationPresetPtr
pPreset( *p
);
337 const double fDuration
= pPreset
->getDuration();
338 sal_Int32 nPos
= LISTBOX_ENTRY_NOTFOUND
;
340 if( fDuration
== 5.0 )
342 else if( fDuration
== 3.0 )
344 else if( fDuration
== 2.0 )
346 else if( fDuration
== 1.0 )
348 else if( fDuration
== 0.5 )
351 mpCBSpeed
->SelectEntryPos( nPos
);
353 bool bHasSpeed
= pPreset
->getDuration() > 0.001;
354 mpCBSpeed
->Enable( bHasSpeed
);
355 mpFTSpeed
->Enable( bHasSpeed
);
357 if( mpCBXPReview
->IsChecked() )
359 mpParent
->preview( pPreset
);
363 void CustomAnimationCreateTabPage::clearEffects()
365 sal_Int32 nPos
= mpLBEffects
->GetEntryCount();
367 delete static_cast< CustomAnimationPresetPtr
* >( mpLBEffects
->GetEntryData( nPos
) );
369 mpLBEffects
->Clear();
372 CustomAnimationPresetPtr
CustomAnimationCreateTabPage::getSelectedPreset() const
374 CustomAnimationPresetPtr pPreset
;
376 if( mpLBEffects
->GetSelectEntryCount() == 1 )
378 void* pEntryData
= mpLBEffects
->GetSelectEntryData();
380 pPreset
= *static_cast< CustomAnimationPresetPtr
* >( pEntryData
);
386 PathKind
CustomAnimationCreateTabPage::getCreatePathKind() const
388 PathKind eKind
= PathKind::NONE
;
390 if( mpLBEffects
->GetSelectEntryCount() == 1 )
392 const sal_Int32 nPos
= mpLBEffects
->GetSelectEntryPos();
393 if( nPos
== mnCurvePathPos
)
395 eKind
= PathKind::CURVE
;
397 else if( nPos
== mnPolygonPathPos
)
399 eKind
= PathKind::POLYGON
;
401 else if( nPos
== mnFreeformPathPos
)
403 eKind
= PathKind::FREEFORM
;
410 double CustomAnimationCreateTabPage::getDuration() const
412 sal_Int32 nPos
= mpCBSpeed
->GetSelectEntryPos();
413 if( (nPos
== LISTBOX_ENTRY_NOTFOUND
) || !mpCBSpeed
->IsEnabled() )
415 CustomAnimationPresetPtr pPreset
= getSelectedPreset();
417 return pPreset
->getDuration();
432 void CustomAnimationCreateTabPage::setDuration( double fDuration
)
435 if( fDuration
< 2.0f
)
437 if( fDuration
< 1.0f
)
446 else if( fDuration
< 5.0f
)
448 if( fDuration
< 3.0f
)
458 mpCBSpeed
->SelectEntryPos( nPos
);
461 bool CustomAnimationCreateTabPage::getIsPreview() const
463 return mpCBXPReview
->IsChecked();
466 void CustomAnimationCreateTabPage::setIsPreview( bool bIsPreview
)
468 mpCBXPReview
->Check( bIsPreview
);
471 bool CustomAnimationCreateTabPage::select( const OUString
& rsPresetId
)
473 sal_Int32 nPos
= mpLBEffects
->GetEntryCount();
476 void* pEntryData
= mpLBEffects
->GetEntryData( nPos
);
479 CustomAnimationPresetPtr
& pPtr
= *static_cast< CustomAnimationPresetPtr
* >(pEntryData
);
480 if( pPtr
.get() && pPtr
->getPresetId() == rsPresetId
)
482 mpLBEffects
->SelectEntryPos( nPos
);
491 CustomAnimationCreateDialog::CustomAnimationCreateDialog( vcl::Window
* pParent
, CustomAnimationPane
* pPane
, const std::vector
< ::com::sun::star::uno::Any
>& rTargets
, bool bHasText
, const OUString
& rsPresetId
, double fDuration
)
492 : TabDialog( pParent
, "CustomAnimationCreate", "modules/simpress/ui/customanimationcreatedialog.ui" )
494 , mrTargets( rTargets
)
495 , mfDuration( fDuration
)
497 get( mpTabControl
, "tabs" );
499 SdOptions
* pOptions
= SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS
);
500 mbIsPreview
= pOptions
->IsPreviewNewEffects();
502 mnEntranceId
= mpTabControl
->GetPageId("entrance");
503 mnEmphasisId
= mpTabControl
->GetPageId("emphasis");
504 mnExitId
= mpTabControl
->GetPageId("exit");
505 mnMPathId
= mpTabControl
->GetPageId("motion_paths");
506 mnMiscId
= mpTabControl
->GetPageId("misc_effects");
508 const CustomAnimationPresets
& rPresets
= CustomAnimationPresets::getCustomAnimationPresets();
509 mpTabPages
[ENTRANCE
] = VclPtr
<CustomAnimationCreateTabPage
>::Create( mpTabControl
, this, mnEntranceId
, rPresets
.getEntrancePresets(), bHasText
);
510 mpTabControl
->SetTabPage( mnEntranceId
, mpTabPages
[ENTRANCE
] );
511 mpTabPages
[EMPHASIS
] = VclPtr
<CustomAnimationCreateTabPage
>::Create( mpTabControl
, this, mnEmphasisId
, rPresets
.getEmphasisPresets(), bHasText
);
512 mpTabControl
->SetTabPage( mnEmphasisId
, mpTabPages
[EMPHASIS
] );
513 mpTabPages
[EXIT
] = VclPtr
<CustomAnimationCreateTabPage
>::Create( mpTabControl
, this, mnExitId
, rPresets
.getExitPresets(), bHasText
);
514 mpTabControl
->SetTabPage( mnExitId
, mpTabPages
[EXIT
] );
515 mpTabPages
[MOTIONPATH
] = VclPtr
<CustomAnimationCreateTabPage
>::Create( mpTabControl
, this, mnMPathId
, rPresets
.getMotionPathsPresets(), bHasText
, true );
516 mpTabControl
->SetTabPage( mnMPathId
, mpTabPages
[MOTIONPATH
] );
517 mpTabPages
[MISCEFFECTS
] = VclPtr
<CustomAnimationCreateTabPage
>::Create( mpTabControl
, this, mnMiscId
, rPresets
.getMiscPresets(), bHasText
);
518 mpTabControl
->SetTabPage( mnMiscId
, mpTabPages
[MISCEFFECTS
] );
520 getCurrentPage()->setDuration( mfDuration
);
521 getCurrentPage()->setIsPreview( mbIsPreview
);
523 mpTabControl
->SetActivatePageHdl( LINK( this, CustomAnimationCreateDialog
, implActivatePagekHdl
) );
524 mpTabControl
->SetDeactivatePageHdl( LINK( this, CustomAnimationCreateDialog
, implDeactivatePagekHdl
) );
528 // select current preset if available
529 if( !rsPresetId
.isEmpty() )
531 for( sal_uInt16 i
= ENTRANCE
; i
<= MISCEFFECTS
; i
++ )
533 if( mpTabPages
[i
]->select( rsPresetId
) )
535 mpTabControl
->SetCurPageId( mpTabPages
[i
]->getId() );
542 CustomAnimationCreateDialog::~CustomAnimationCreateDialog()
547 void CustomAnimationCreateDialog::dispose()
551 SdOptions
* pOptions
= SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS
);
552 pOptions
->SetPreviewNewEffects( getCurrentPage()->getIsPreview() );
554 mpTabPages
[ENTRANCE
].disposeAndClear();
555 mpTabPages
[EMPHASIS
].disposeAndClear();
556 mpTabPages
[EXIT
].disposeAndClear();
557 mpTabPages
[MOTIONPATH
].disposeAndClear();
558 mpTabPages
[MISCEFFECTS
].disposeAndClear();
560 mpTabControl
.clear();
562 TabDialog::dispose();
565 CustomAnimationCreateTabPage
* CustomAnimationCreateDialog::getCurrentPage() const
567 sal_Int16 curPageId
= mpTabControl
->GetCurPageId();
569 for( sal_uInt16 i
= ENTRANCE
; i
<= MISCEFFECTS
; i
++ )
571 if( mpTabPages
[i
]->getId() == curPageId
)
572 return mpTabPages
[i
];
574 return mpTabPages
[MOTIONPATH
];
577 PathKind
CustomAnimationCreateDialog::getCreatePathKind() const
579 return getCurrentPage()->getCreatePathKind();
582 CustomAnimationPresetPtr
CustomAnimationCreateDialog::getSelectedPreset() const
584 return getCurrentPage()->getSelectedPreset();
587 double CustomAnimationCreateDialog::getSelectedDuration() const
589 return getCurrentPage()->getDuration();
592 IMPL_LINK_NOARG(CustomAnimationCreateDialog
, implActivatePagekHdl
)
594 getCurrentPage()->setDuration( mfDuration
);
595 getCurrentPage()->setIsPreview( mbIsPreview
);
599 IMPL_LINK_NOARG_TYPED(CustomAnimationCreateDialog
, implDeactivatePagekHdl
, TabControl
*, bool)
601 mfDuration
= getCurrentPage()->getDuration();
602 mbIsPreview
= getCurrentPage()->getIsPreview();
606 void CustomAnimationCreateDialog::preview( const CustomAnimationPresetPtr
& pPreset
) const
608 MainSequencePtr
pSequence( new MainSequence() );
610 std::vector
< Any
>::const_iterator
aIter( mrTargets
.begin() );
611 const std::vector
< Any
>::const_iterator
aEnd( mrTargets
.end() );
613 const double fDuration
= getSelectedDuration();
616 while( aIter
!= aEnd
)
618 CustomAnimationEffectPtr
pNew(
619 pSequence
->append( pPreset
, (*aIter
++), fDuration
) );
624 pNew
->setNodeType( EffectNodeType::WITH_PREVIOUS
);
627 mpPane
->preview( pSequence
->getRootNode() );
632 vcl::Window
* lcl_GetTopmostParent( vcl::Window
* pWindow
)
634 vcl::Window
* pResult
= 0;
635 vcl::Window
* pCurrent
= pWindow
? pWindow
->GetParent() : 0;
639 pCurrent
= pCurrent
->GetParent();
645 void CustomAnimationCreateDialog::setPosition()
647 SvtViewOptions
aDlgOpt(E_TABDIALOG
, OStringToOUString(GetHelpId(), RTL_TEXTENCODING_UTF8
));
648 if ( aDlgOpt
.Exists() )
650 SetWindowState( OUStringToOString(aDlgOpt
.GetWindowState(),
651 RTL_TEXTENCODING_ASCII_US
) );
655 // default position: aligned with right edge of parent
656 vcl::Window
* pParent
= lcl_GetTopmostParent( this );
659 Point
aPos( GetPosPixel());
660 Size
aSize( GetSizePixel());
661 Size
aParentSize( pParent
->GetSizePixel());
664 aPos
.setX( aParentSize
.getWidth() - aSize
.getWidth() );
665 aPos
.setY( (aParentSize
.getHeight() - aSize
.getHeight()) / 2 );
671 void CustomAnimationCreateDialog::storePosition()
673 // save settings (screen position and current page)
674 SvtViewOptions
aDlgOpt(E_TABDIALOG
, OStringToOUString(GetHelpId(), RTL_TEXTENCODING_UTF8
));
675 aDlgOpt
.SetWindowState(OStringToOUString(
676 GetWindowState(WINDOWSTATE_MASK_POS
), RTL_TEXTENCODING_ASCII_US
));
681 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */