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/presentation/AnimationEffect.hpp>
21 #include <com/sun/star/presentation/AnimationSpeed.hpp>
22 #include <svx/xoutbmp.hxx>
24 #include <svl/eitem.hxx>
25 #include <svx/svdograf.hxx>
26 #include <svx/svdogrp.hxx>
27 #include <sfx2/basedlgs.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/progress.hxx>
30 #include <vcl/msgbox.hxx>
32 #include "anminfo.hxx"
33 #include "animobjs.hxx"
35 #include "strings.hrc"
36 #include "sdresid.hxx"
38 #include "drawdoc.hxx"
40 #include "res_bmp.hrc"
41 #include "ViewShell.hxx"
43 #include <vcl/svapp.hxx>
44 #include <vcl/settings.hxx>
46 #include <EffectMigration.hxx>
51 using namespace ::com::sun::star
;
58 SdDisplay::SdDisplay(vcl::Window
* pWin
)
62 SetMapMode( MAP_PIXEL
);
63 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
64 SetBackground( Wallpaper( Color( rStyles
.GetFieldColor() ) ) );
67 SdDisplay::~SdDisplay()
71 void SdDisplay::SetBitmapEx( BitmapEx
* pBmpEx
)
79 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
80 const Color aFillColor
= rStyles
.GetFieldColor();
81 aBitmapEx
.Erase(aFillColor
);
85 void SdDisplay::Paint( vcl::RenderContext
& /*rRenderContext*/, const Rectangle
& )
88 Size aSize
= GetOutputSize();
89 Size aBmpSize
= aBitmapEx
.GetBitmap().GetSizePixel();
90 aBmpSize
.Width() = (long) ( (double) aBmpSize
.Width() * (double) aScale
);
91 aBmpSize
.Height() = (long) ( (double) aBmpSize
.Height() * (double) aScale
);
93 if( aBmpSize
.Width() < aSize
.Width() )
94 aPt
.X() = ( aSize
.Width() - aBmpSize
.Width() ) / 2;
95 if( aBmpSize
.Height() < aSize
.Height() )
96 aPt
.Y() = ( aSize
.Height() - aBmpSize
.Height() ) / 2;
98 aBitmapEx
.Draw( this, aPt
, aBmpSize
);
101 void SdDisplay::SetScale( const Fraction
& rFrac
)
106 Size
SdDisplay::GetOptimalSize() const
108 return LogicToPixel(Size(147, 87), MAP_APPFONT
);
111 void SdDisplay::DataChanged( const DataChangedEvent
& rDCEvt
)
113 Control::DataChanged( rDCEvt
);
115 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
117 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
118 SetBackground( Wallpaper( Color( rStyles
.GetFieldColor() ) ) );
119 SetDrawMode( GetSettings().GetStyleSettings().GetHighContrastMode()
120 ? sd::OUTPUT_DRAWMODE_CONTRAST
121 : sd::OUTPUT_DRAWMODE_COLOR
);
125 const size_t AnimationWindow::EMPTY_FRAMELIST
= std::numeric_limits
<size_t>::max();
128 * AnimationWindow - FloatingWindow
130 AnimationWindow::AnimationWindow(SfxBindings
* pInBindings
, SfxChildWindow
*pCW
, vcl::Window
* pParent
)
131 : SfxDockingWindow(pInBindings
, pCW
, pParent
,
132 "DockingAnimation", "modules/simpress/ui/dockinganimation.ui")
134 , m_nCurrentFrame(EMPTY_FRAMELIST
)
137 , pBindings(pInBindings
)
139 get(m_pBtnFirst
, "first");
140 get(m_pBtnReverse
, "prev");
141 get(m_pBtnStop
, "stop");
142 get(m_pBtnPlay
, "next");
143 get(m_pBtnLast
, "last");
144 get(m_pNumFldBitmap
, "numbitmap");
145 get(m_pTimeField
, "duration");
146 m_pTimeField
->SetDuration(true);
147 m_pTimeField
->EnforceValidValue(true);
148 m_pTimeField
->SetMax(tools::Time(0, 0, 59, 99*tools::Time::nanoPerCenti
));
149 get(m_pLbLoopCount
, "loopcount");
150 get(m_pBtnGetOneObject
, "getone");
151 get(m_pBtnGetAllObjects
, "getall");
152 get(m_pBtnRemoveBitmap
, "delone");
153 get(m_pBtnRemoveAll
, "delall");
154 get(m_pFiCount
, "count");
155 get(m_pRbtGroup
, "group");
156 get(m_pRbtBitmap
, "bitmap");
157 get(m_pFtAdjustment
, "alignmentft");
158 get(m_pLbAdjustment
, "alignment");
159 get(m_pBtnCreateGroup
, "create");
161 m_pCtlDisplay
= VclPtr
<SdDisplay
>::Create(get
<Window
>("box"));
162 m_pCtlDisplay
->set_hexpand(true);
163 m_pCtlDisplay
->set_vexpand(true);
164 m_pCtlDisplay
->Show();
166 //undo SfxDockingWindow HelpId clear hack
167 reverseUniqueHelpIdHack(*this);
169 // create new document with page
170 pMyDoc
= new SdDrawDocument(DOCUMENT_TYPE_IMPRESS
, NULL
);
171 SdPage
* pPage
= pMyDoc
->AllocSdPage(false);
172 pMyDoc
->InsertPage(pPage
);
174 pControllerItem
= new AnimationControllerItem( SID_ANIMATOR_STATE
, this, pBindings
);
176 // as long as not in the resource
177 m_pTimeField
->SetFormat( TimeFieldFormat::F_SEC_CS
);
179 m_pBtnFirst
->SetClickHdl( LINK( this, AnimationWindow
, ClickFirstHdl
) );
180 m_pBtnReverse
->SetClickHdl( LINK( this, AnimationWindow
, ClickPlayHdl
) );
181 m_pBtnStop
->SetClickHdl( LINK( this, AnimationWindow
, ClickStopHdl
) );
182 m_pBtnPlay
->SetClickHdl( LINK( this, AnimationWindow
, ClickPlayHdl
) );
183 m_pBtnLast
->SetClickHdl( LINK( this, AnimationWindow
, ClickLastHdl
) );
185 m_pBtnGetOneObject
->SetClickHdl( LINK( this, AnimationWindow
, ClickGetObjectHdl
) );
186 m_pBtnGetAllObjects
->SetClickHdl( LINK( this, AnimationWindow
, ClickGetObjectHdl
) );
187 m_pBtnRemoveBitmap
->SetClickHdl( LINK( this, AnimationWindow
, ClickRemoveBitmapHdl
) );
188 m_pBtnRemoveAll
->SetClickHdl( LINK( this, AnimationWindow
, ClickRemoveBitmapHdl
) );
190 m_pRbtGroup
->SetClickHdl( LINK( this, AnimationWindow
, ClickRbtHdl
) );
191 m_pRbtBitmap
->SetClickHdl( LINK( this, AnimationWindow
, ClickRbtHdl
) );
192 m_pBtnCreateGroup
->SetClickHdl( LINK( this, AnimationWindow
, ClickCreateGroupHdl
) );
193 m_pNumFldBitmap
->SetModifyHdl( LINK( this, AnimationWindow
, ModifyBitmapHdl
) );
194 m_pTimeField
->SetModifyHdl( LINK( this, AnimationWindow
, ModifyTimeHdl
) );
197 m_pCtlDisplay
->SetBorderStyle(WindowBorderStyle::MONO
);
199 SetMinOutputSizePixel(GetOptimalSize());
203 // the animator is empty; no animation group can be created
204 m_pBtnCreateGroup
->Disable();
207 AnimationWindow::~AnimationWindow()
212 void AnimationWindow::dispose()
214 DELETEZ( pControllerItem
);
216 for (size_t i
= 0; i
< m_FrameList
.size(); ++i
)
218 delete m_FrameList
[i
].first
;
219 delete m_FrameList
[i
].second
;
222 m_nCurrentFrame
= EMPTY_FRAMELIST
;
227 m_pCtlDisplay
.disposeAndClear();
229 m_pBtnReverse
.clear();
233 m_pNumFldBitmap
.clear();
234 m_pTimeField
.clear();
235 m_pLbLoopCount
.clear();
236 m_pBtnGetOneObject
.clear();
237 m_pBtnGetAllObjects
.clear();
238 m_pBtnRemoveBitmap
.clear();
239 m_pBtnRemoveAll
.clear();
242 m_pRbtBitmap
.clear();
243 m_pFtAdjustment
.clear();
244 m_pLbAdjustment
.clear();
245 m_pBtnCreateGroup
.clear();
247 SfxDockingWindow::dispose();
250 IMPL_LINK_NOARG(AnimationWindow
, ClickFirstHdl
)
252 m_nCurrentFrame
= (m_FrameList
.empty()) ? EMPTY_FRAMELIST
: 0;
258 IMPL_LINK_NOARG(AnimationWindow
, ClickStopHdl
)
264 IMPL_LINK( AnimationWindow
, ClickPlayHdl
, void *, p
)
266 ScopeLockGuard
aGuard( maPlayLock
);
269 bool bDisableCtrls
= false;
270 size_t const nCount
= m_FrameList
.size();
271 bool bReverse
= p
== m_pBtnReverse
;
273 // it is difficult to find it later on
274 bool bRbtGroupEnabled
= m_pRbtGroup
->IsEnabled();
275 bool bBtnGetAllObjectsEnabled
= m_pBtnGetAllObjects
->IsEnabled();
276 bool bBtnGetOneObjectEnabled
= m_pBtnGetOneObject
->IsEnabled();
278 // calculate overall time
279 tools::Time
aTime( 0 );
281 if( m_pRbtBitmap
->IsChecked() )
283 for (size_t i
= 0; i
< nCount
; ++i
)
285 aTime
+= *m_FrameList
[i
].second
;
287 nFullTime
= aTime
.GetMSFromTime();
291 nFullTime
= nCount
* 100;
292 aTime
.MakeTimeFromMS( nFullTime
);
295 // StatusBarManager from 1 second
296 SfxProgress
* pProgress
= NULL
;
297 if( nFullTime
>= 1000 )
299 bDisableCtrls
= true;
300 m_pBtnStop
->Enable();
301 m_pBtnStop
->Update();
302 OUString
aStr("Animator:"); // here we should think about something smart
303 pProgress
= new SfxProgress( NULL
, aStr
, nFullTime
);
306 sal_uLong nTmpTime
= 0;
308 bool bCount
= i
< nCount
;
313 while( bCount
&& bMovie
)
315 // make list and view consistent
316 assert(i
< m_FrameList
.size());
319 UpdateControl(bDisableCtrls
);
321 if( m_pRbtBitmap
->IsChecked() )
323 tools::Time
*const pTime
= m_FrameList
[i
].second
;
326 m_pTimeField
->SetTime( *pTime
);
327 sal_uLong nTime
= pTime
->GetMSFromTime();
329 WaitInEffect( nTime
, nTmpTime
, pProgress
);
334 WaitInEffect( 100, nTmpTime
, pProgress
);
356 // Move i back into valid range.
362 // to re-enable the controls
366 assert(i
== m_nCurrentFrame
);
373 m_pBtnStop
->Disable();
376 m_pRbtGroup
->Enable( bRbtGroupEnabled
);
377 m_pBtnGetAllObjects
->Enable( bBtnGetAllObjectsEnabled
);
378 m_pBtnGetOneObject
->Enable( bBtnGetOneObjectEnabled
);
383 IMPL_LINK_NOARG(AnimationWindow
, ClickLastHdl
)
386 (m_FrameList
.empty()) ? EMPTY_FRAMELIST
: m_FrameList
.size() - 1 ;
392 IMPL_LINK( AnimationWindow
, ClickRbtHdl
, void *, p
)
394 if (m_FrameList
.empty() || p
== m_pRbtGroup
|| m_pRbtGroup
->IsChecked())
396 m_pTimeField
->SetText( OUString() );
397 m_pTimeField
->Enable( false );
398 m_pLbLoopCount
->Enable( false );
400 else if( p
== m_pRbtBitmap
|| m_pRbtBitmap
->IsChecked() )
402 sal_uLong n
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue());
405 tools::Time
*const pTime
= m_FrameList
[n
- 1].second
;
407 m_pTimeField
->SetTime( *pTime
);
409 m_pTimeField
->Enable();
410 m_pLbLoopCount
->Enable();
416 IMPL_LINK( AnimationWindow
, ClickGetObjectHdl
, void *, pBtn
)
418 bAllObjects
= pBtn
== m_pBtnGetAllObjects
;
420 // Code now in AddObj()
421 SfxBoolItem
aItem( SID_ANIMATOR_ADD
, true );
423 GetBindings().GetDispatcher()->Execute(
424 SID_ANIMATOR_ADD
, SfxCallMode::SLOT
| SfxCallMode::RECORD
, &aItem
, 0L );
428 IMPL_LINK( AnimationWindow
, ClickRemoveBitmapHdl
, void *, pBtn
)
430 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PK_STANDARD
);
433 // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access
434 if (pBtn
== m_pBtnRemoveBitmap
&& EMPTY_FRAMELIST
!= m_nCurrentFrame
)
436 delete m_FrameList
[m_nCurrentFrame
].first
;
437 delete m_FrameList
[m_nCurrentFrame
].second
;
438 m_FrameList
.erase(m_FrameList
.begin() + m_nCurrentFrame
);
440 pObject
= pPage
->GetObj(m_nCurrentFrame
);
441 // Through acquisition of the AnimatedGIFs, objects does not need to
445 pObject
= pPage
->RemoveObject(m_nCurrentFrame
);
446 DBG_ASSERT(pObject
, "Clone not found during deletion");
447 SdrObject::Free( pObject
);
448 pPage
->RecalcObjOrdNums();
451 if (m_nCurrentFrame
>= m_FrameList
.size())
453 // tdf#95298 last frame was deleted, try to use the one before it or go on empty state
454 m_nCurrentFrame
= m_FrameList
.empty() ? EMPTY_FRAMELIST
: m_FrameList
.size() - 1;
457 else // delete everything
459 ScopedVclPtrInstance
< WarningBox
> aWarnBox( this, WB_YES_NO
, SD_RESSTR( STR_ASK_DELETE_ALL_PICTURES
) );
460 short nReturn
= aWarnBox
->Execute();
462 if( nReturn
== RET_YES
)
465 for (size_t i
= m_FrameList
.size(); i
> 0; )
468 delete m_FrameList
[i
].first
;
470 pObject
= pPage
->GetObj( i
);
473 pObject
= pPage
->RemoveObject( i
);
474 DBG_ASSERT(pObject
, "Clone not found during deletion");
475 SdrObject::Free( pObject
);
476 //pPage->RecalcObjOrdNums();
479 delete m_FrameList
[i
].second
;
482 m_nCurrentFrame
= EMPTY_FRAMELIST
;
486 // can we create a animation group
487 if (m_FrameList
.empty())
489 m_pBtnCreateGroup
->Disable();
490 // if previous disabled by acquisition of AnimatedGIFs:
491 //m_pRbtBitmap->Enable();
492 m_pRbtGroup
->Enable();
495 // calculate and set zoom for DisplayWin
496 Fraction
aFrac(GetScale());
497 m_pCtlDisplay
->SetScale(aFrac
);
504 IMPL_LINK_NOARG(AnimationWindow
, ClickCreateGroupHdl
)
506 // Code now in CreatePresObj()
507 SfxBoolItem
aItem( SID_ANIMATOR_CREATE
, true );
509 GetBindings().GetDispatcher()->Execute(
510 SID_ANIMATOR_CREATE
, SfxCallMode::SLOT
| SfxCallMode::RECORD
, &aItem
, 0L );
514 IMPL_LINK_NOARG(AnimationWindow
, ModifyBitmapHdl
)
516 sal_uLong nBmp
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue());
518 if (nBmp
> m_FrameList
.size())
520 nBmp
= m_FrameList
.size();
523 m_nCurrentFrame
= nBmp
- 1;
530 IMPL_LINK_NOARG(AnimationWindow
, ModifyTimeHdl
)
532 sal_uLong nPos
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue() - 1);
534 tools::Time
*const pTime
= m_FrameList
[nPos
].second
;
536 *pTime
= m_pTimeField
->GetTime();
541 void AnimationWindow::UpdateControl(bool const bDisableCtrls
)
543 // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access
544 if (!m_FrameList
.empty() && EMPTY_FRAMELIST
!= m_nCurrentFrame
)
546 BitmapEx
aBmp(*m_FrameList
[m_nCurrentFrame
].first
);
548 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PK_STANDARD
);
549 SdrObject
*const pObject
=
550 static_cast<SdrObject
*>(pPage
->GetObj(m_nCurrentFrame
));
553 ScopedVclPtrInstance
< VirtualDevice
> pVD
;
554 Rectangle
aObjRect( pObject
->GetCurrentBoundRect() );
555 Size
aObjSize( aObjRect
.GetSize() );
556 Point
aOrigin( Point( -aObjRect
.Left(), -aObjRect
.Top() ) );
557 MapMode
aMap( pVD
->GetMapMode() );
558 aMap
.SetMapUnit( MAP_100TH_MM
);
559 aMap
.SetOrigin( aOrigin
);
560 pVD
->SetMapMode( aMap
);
561 pVD
->SetOutputSize( aObjSize
);
562 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
563 pVD
->SetBackground( Wallpaper( rStyles
.GetFieldColor() ) );
564 pVD
->SetDrawMode( rStyles
.GetHighContrastMode()
565 ? sd::OUTPUT_DRAWMODE_CONTRAST
566 : sd::OUTPUT_DRAWMODE_COLOR
);
568 pObject
->SingleObjectPainter( *pVD
.get() );
569 aBmp
= BitmapEx( pVD
->GetBitmap( aObjRect
.TopLeft(), aObjSize
) );
572 m_pCtlDisplay
->SetBitmapEx(&aBmp
);
576 m_pCtlDisplay
->SetBitmapEx(0);
578 m_pCtlDisplay
->Invalidate();
579 m_pCtlDisplay
->Update();
581 m_pFiCount
->SetText(OUString::number(
582 m_FrameList
.size()));
584 if (!m_FrameList
.empty() && !bMovie
)
586 size_t nIndex
= m_nCurrentFrame
+ 1;
587 m_pNumFldBitmap
->SetValue(nIndex
);
589 // if there is at least 1 object in the list
590 m_pBtnFirst
->Enable();
591 m_pBtnReverse
->Enable();
592 m_pBtnPlay
->Enable();
593 m_pBtnLast
->Enable();
594 m_pNumFldBitmap
->Enable();
595 m_pTimeField
->Enable();
596 m_pLbLoopCount
->Enable();
597 m_pBtnRemoveBitmap
->Enable();
598 m_pBtnRemoveAll
->Enable();
602 // if no object is in the list
603 m_pBtnFirst
->Enable( false );
604 m_pBtnReverse
->Enable( false );
605 m_pBtnPlay
->Enable( false );
606 m_pBtnLast
->Enable( false );
607 m_pNumFldBitmap
->Enable( false );
608 m_pTimeField
->Enable( false );
609 m_pLbLoopCount
->Enable( false );
610 m_pBtnRemoveBitmap
->Enable( false );
611 m_pBtnRemoveAll
->Enable( false );
614 if( bMovie
&& bDisableCtrls
)
616 m_pBtnGetOneObject
->Enable( false );
617 m_pBtnGetAllObjects
->Enable( false );
618 m_pRbtGroup
->Enable( false );
619 m_pRbtBitmap
->Enable( false );
620 m_pBtnCreateGroup
->Enable( false );
621 m_pFtAdjustment
->Enable( false );
622 m_pLbAdjustment
->Enable( false );
626 // enable 'group object' only if it is not a Animated GIF
627 if (m_FrameList
.empty())
629 m_pRbtGroup
->Enable();
632 m_pRbtBitmap
->Enable();
633 m_pBtnCreateGroup
->Enable(!m_FrameList
.empty());
634 m_pFtAdjustment
->Enable( true );
635 m_pLbAdjustment
->Enable( true );
641 void AnimationWindow::ResetAttrs()
643 m_pRbtGroup
->Check();
644 m_pLbAdjustment
->SelectEntryPos( BA_CENTER
);
646 m_pLbLoopCount
->SelectEntryPos( m_pLbLoopCount
->GetEntryCount() - 1);
651 void AnimationWindow::WaitInEffect( sal_uLong nMilliSeconds
, sal_uLong nTime
,
652 SfxProgress
* pProgress
) const
654 sal_uInt64 aEnd
= tools::Time::GetSystemTicks() + nMilliSeconds
;
655 sal_uInt64 aCurrent
= tools::Time::GetSystemTicks();
656 while (aCurrent
< aEnd
)
658 aCurrent
= tools::Time::GetSystemTicks();
661 pProgress
->SetState( nTime
+ nMilliSeconds
+ aCurrent
- aEnd
);
663 Application::Reschedule();
670 Fraction
AnimationWindow::GetScale()
673 size_t const nCount
= m_FrameList
.size();
677 for (size_t i
= 0; i
< nCount
; i
++)
679 BitmapEx
*const pBitmap
= m_FrameList
[i
].first
;
680 Size
aTempSize( pBitmap
->GetBitmap().GetSizePixel() );
681 aBmpSize
.Width() = std::max( aBmpSize
.Width(), aTempSize
.Width() );
682 aBmpSize
.Height() = std::max( aBmpSize
.Height(), aTempSize
.Height() );
685 aBmpSize
.Width() += 10;
686 aBmpSize
.Height() += 10;
688 Size
aDisplaySize(m_pCtlDisplay
->GetOutputSize());
690 aFrac
= Fraction( std::min( (double)aDisplaySize
.Width() / (double)aBmpSize
.Width(),
691 (double)aDisplaySize
.Height() / (double)aBmpSize
.Height() ) );
696 void AnimationWindow::Resize()
698 SfxDockingWindow::Resize();
699 Fraction
aFrac(GetScale());
700 m_pCtlDisplay
->SetScale(aFrac
);
703 bool AnimationWindow::Close()
705 if( maPlayLock
.isLocked() )
711 SfxBoolItem
aItem( SID_ANIMATION_OBJECTS
, false );
713 GetBindings().GetDispatcher()->Execute(
714 SID_ANIMATION_OBJECTS
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
, &aItem
, 0L );
716 SfxDockingWindow::Close();
722 void AnimationWindow::FillInfo( SfxChildWinInfo
& rInfo
) const
724 SfxDockingWindow::FillInfo( rInfo
) ;
727 void AnimationWindow::AddObj (::sd::View
& rView
)
729 // finish text entry mode to ensure that bitmap is identical with object
730 if( rView
.IsTextEdit() )
731 rView
.SdrEndTextEdit();
733 // clone object(s) and insert the clone(s) into the list
734 const SdrMarkList
& rMarkList
= rView
.GetMarkedObjectList();
735 const size_t nMarkCount
= rMarkList
.GetMarkCount();
736 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PK_STANDARD
);
737 const size_t nCloneCount
= pPage
->GetObjCount();
741 // If it is ONE animation object or one group object, which was
742 // 'individually taken', we insert the objects separately
743 bool bAnimObj
= false;
744 if( nMarkCount
== 1 )
746 SdrMark
* pMark
= rMarkList
.GetMark(0);
747 SdrObject
* pObject
= pMark
->GetMarkedSdrObj();
748 SdAnimationInfo
* pAnimInfo
= rView
.GetDoc().GetAnimationInfo( pObject
);
749 sal_uInt32 nInv
= pObject
->GetObjInventor();
750 sal_uInt16 nId
= pObject
->GetObjIdentifier();
752 // Animated Bitmap (GIF)
753 if( nInv
== SdrInventor
&& nId
== OBJ_GRAF
&& static_cast<SdrGrafObj
*>( pObject
)->IsAnimated() )
755 const SdrGrafObj
* pGrafObj
= static_cast<SdrGrafObj
*>(pObject
);
756 Graphic
aGraphic( pGrafObj
->GetTransformedGraphic() );
757 sal_uInt16 nCount
= 0;
759 if( aGraphic
.IsAnimated() )
760 nCount
= aGraphic
.GetAnimation().Count();
764 const Animation
aAnimation( aGraphic
.GetAnimation() );
766 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
768 const AnimationBitmap
& rAnimBmp
= aAnimation
.Get( i
);
770 BitmapEx
*const pBitmapEx
=
771 new BitmapEx(rAnimBmp
.aBmpEx
);
776 long nLoopCount
= aAnimation
.GetLoopCount();
778 if( !nLoopCount
) // endless
779 m_pLbLoopCount
->SelectEntryPos( m_pLbLoopCount
->GetEntryCount() - 1);
781 m_pLbLoopCount
->SelectEntry(OUString::number( nLoopCount
) );
784 long nTime
= rAnimBmp
.nWait
;
785 ::tools::Time
* pTime
= new ::tools::Time( 0, 0, nTime
/ 100, nTime
% 100 );
786 size_t nIndex
= m_nCurrentFrame
+ 1;
788 m_FrameList
.begin() + nIndex
,
789 ::std::make_pair(pBitmapEx
, pTime
));
791 // increment => next one inserted after this one
794 // if a animated GIF is taken, only such one can be created
795 m_pRbtBitmap
->Check();
796 m_pRbtGroup
->Enable( false );
800 else if( bAllObjects
|| ( pAnimInfo
&& pAnimInfo
->mbIsMovie
) )
803 SdrObjList
* pObjList
= static_cast<SdrObjGroup
*>(pObject
)->GetSubList();
805 for( size_t nObject
= 0; nObject
< pObjList
->GetObjCount(); ++nObject
)
807 SdrObject
* pSnapShot
= pObjList
->GetObj( nObject
);
809 BitmapEx
*const pBitmapEx
= new BitmapEx(
810 SdrExchangeView::GetObjGraphic(
811 pSnapShot
->GetModel(), pSnapShot
).GetBitmapEx() );
813 ::tools::Time
* pTime
= new ::tools::Time( m_pTimeField
->GetTime() );
814 size_t nIndex
= m_nCurrentFrame
+ 1;
816 m_FrameList
.begin() + nIndex
,
817 ::std::make_pair(pBitmapEx
, pTime
));
819 // increment => next one inserted after this one
823 pPage
->InsertObject(pSnapShot
->Clone(), m_nCurrentFrame
);
828 // also one single animated object
829 if( !bAnimObj
&& !( bAllObjects
&& nMarkCount
> 1 ) )
831 BitmapEx
*const pBitmapEx
=
832 new BitmapEx(rView
.GetAllMarkedGraphic().GetBitmapEx());
834 ::tools::Time
* pTime
= new ::tools::Time( m_pTimeField
->GetTime() );
836 size_t nIndex
= m_nCurrentFrame
+ 1;
838 m_FrameList
.begin() + nIndex
,
839 ::std::make_pair(pBitmapEx
, pTime
));
843 if( nMarkCount
== 1 && !bAnimObj
)
845 SdrMark
* pMark
= rMarkList
.GetMark(0);
846 SdrObject
* pObject
= pMark
->GetMarkedSdrObj();
847 SdrObject
* pClone
= pObject
->Clone();
848 size_t nIndex
= m_nCurrentFrame
+ 1;
849 pPage
->InsertObject(pClone
, nIndex
);
851 // several objects: group the clones
852 else if (nMarkCount
> 1)
854 // take objects separately
857 for( size_t nObject
= 0; nObject
< nMarkCount
; ++nObject
)
860 SdrObject
* pObject
= rMarkList
.GetMark( nObject
)->GetMarkedSdrObj();
862 BitmapEx
*const pBitmapEx
= new BitmapEx(
863 SdrExchangeView::GetObjGraphic(
864 pObject
->GetModel(), pObject
).GetBitmapEx() );
866 ::tools::Time
* pTime
= new ::tools::Time( m_pTimeField
->GetTime() );
868 size_t nIndex
= m_nCurrentFrame
+ 1;
870 m_FrameList
.begin() + nIndex
,
871 ::std::make_pair(pBitmapEx
, pTime
));
873 // increment => next one inserted after this one
876 pPage
->InsertObject(pObject
->Clone(), m_nCurrentFrame
);
878 bAnimObj
= true; // that we don't change again
882 SdrObjGroup
* pCloneGroup
= new SdrObjGroup
;
883 SdrObjList
* pObjList
= pCloneGroup
->GetSubList();
885 for (size_t nObject
= 0; nObject
< nMarkCount
; ++nObject
)
886 pObjList
->InsertObject(rMarkList
.GetMark(nObject
)->GetMarkedSdrObj()->Clone());
888 size_t nIndex
= m_nCurrentFrame
+ 1;
889 pPage
->InsertObject(pCloneGroup
, nIndex
);
898 // if there was nothing in the animator before but now is something
899 // there, we can create a animation group
900 if (nCloneCount
== 0 && !m_FrameList
.empty())
902 m_pBtnCreateGroup
->Enable();
905 // calculate and set zoom for DisplayWin
906 Fraction
aFrac( GetScale() );
907 m_pCtlDisplay
->SetScale(aFrac
);
913 void AnimationWindow::CreateAnimObj (::sd::View
& rView
)
915 vcl::Window
* pOutWin
= static_cast< vcl::Window
*>(rView
.GetFirstOutputDevice()); // GetWin( 0 );
916 DBG_ASSERT( pOutWin
, "Window does not exist!" );
918 // find window center
919 const MapMode
aMap100( MAP_100TH_MM
);
922 Size
aTemp( pOutWin
->GetOutputSizePixel() );
923 const Point
aWindowCenter( pOutWin
->PixelToLogic( Point( aTemp
.Width() >> 1, aTemp
.Height() >> 1 ) ) );
924 const OutputDevice
* pDefDev
= Application::GetDefaultDevice();
925 const size_t nCount
= m_FrameList
.size();
926 BitmapAdjustment eBA
= (BitmapAdjustment
) m_pLbAdjustment
->GetSelectEntryPos();
928 // find biggest bitmap
929 for (size_t i
= 0; i
< nCount
; ++i
)
931 const BitmapEx
& rBmpEx
= *m_FrameList
[i
].first
;
932 const Graphic
aGraphic( rBmpEx
);
934 const Size
aTmpSizePix( rBmpEx
.GetSizePixel() );
936 if ( aGraphic
.GetPrefMapMode().GetMapUnit() == MAP_PIXEL
)
937 aTmpSizeLog
= pDefDev
->PixelToLogic( aGraphic
.GetPrefSize(), aMap100
);
939 aTmpSizeLog
= OutputDevice::LogicToLogic( aGraphic
.GetPrefSize(), aGraphic
.GetPrefMapMode(), aMap100
);
941 aMaxSizeLog
.Width() = std::max( aMaxSizeLog
.Width(), aTmpSizeLog
.Width() );
942 aMaxSizeLog
.Height() = std::max( aMaxSizeLog
.Height(), aTmpSizeLog
.Height() );
944 aMaxSizePix
.Width() = std::max( aMaxSizePix
.Width(), aTmpSizePix
.Width() );
945 aMaxSizePix
.Height() = std::max( aMaxSizePix
.Height(), aTmpSizePix
.Height() );
948 SdrPageView
* pPV
= rView
.GetSdrPageView();
950 if( m_pRbtBitmap
->IsChecked() )
952 // create bitmap group (Animated GIF)
953 Animation aAnimation
;
956 for (size_t i
= 0; i
< nCount
; ++i
)
958 tools::Time
*const pTime
= m_FrameList
[i
].second
;
959 long nTime
= pTime
->GetNanoSec();
960 nTime
+= pTime
->GetSec() * 100;
962 BitmapEx
const*const pBitmapEx
= m_FrameList
[i
].first
;
964 // calculate offset for the specified direction
965 const Size
aBitmapSize( pBitmapEx
->GetSizePixel() );
973 aPt
.Y() = (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1;
977 aPt
.Y() = aMaxSizePix
.Height() - aBitmapSize
.Height();
981 aPt
.X() = (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1;
985 aPt
.X() = (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1;
986 aPt
.Y() = (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1;
990 aPt
.X() = (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1;
991 aPt
.Y() = aMaxSizePix
.Height() - aBitmapSize
.Height();
995 aPt
.X() = aMaxSizePix
.Width() - aBitmapSize
.Width();
999 aPt
.X() = aMaxSizePix
.Width() - aBitmapSize
.Width();
1000 aPt
.Y() = (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1;
1004 aPt
.X() = aMaxSizePix
.Width() - aBitmapSize
.Width();
1005 aPt
.Y() = aMaxSizePix
.Height() - aBitmapSize
.Height();
1010 // find LoopCount (number of passes)
1011 AnimationBitmap aAnimBmp
;
1012 long nLoopCount
= 0L;
1013 sal_Int32 nPos
= m_pLbLoopCount
->GetSelectEntryPos();
1015 if( nPos
!= LISTBOX_ENTRY_NOTFOUND
&& nPos
!= m_pLbLoopCount
->GetEntryCount() - 1 ) // endless
1016 nLoopCount
= (long) m_pLbLoopCount
->GetSelectEntry().toInt32();
1018 aAnimBmp
.aBmpEx
= *pBitmapEx
;
1019 aAnimBmp
.aPosPix
= aPt
;
1020 aAnimBmp
.aSizePix
= aBitmapSize
;
1021 aAnimBmp
.nWait
= nTime
;
1022 aAnimBmp
.eDisposal
= DISPOSE_BACK
;
1023 aAnimBmp
.bUserInput
= false;
1025 aAnimation
.Insert( aAnimBmp
);
1026 aAnimation
.SetDisplaySizePixel( aMaxSizePix
);
1027 aAnimation
.SetLoopCount( nLoopCount
);
1030 SdrGrafObj
* pGrafObj
= new SdrGrafObj( Graphic( aAnimation
) );
1031 const Point
aOrg( aWindowCenter
.X() - ( aMaxSizeLog
.Width() >> 1 ), aWindowCenter
.Y() - ( aMaxSizeLog
.Height() >> 1 ) );
1033 pGrafObj
->SetLogicRect( Rectangle( aOrg
, aMaxSizeLog
) );
1034 rView
.InsertObjectAtView( pGrafObj
, *pPV
, SdrInsertFlags::SETDEFLAYER
);
1038 // calculate offset for the specified direction
1040 SdrObject
* pClone
= NULL
;
1041 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PK_STANDARD
);
1043 for (size_t i
= 0; i
< nCount
; ++i
)
1045 pClone
= pPage
->GetObj(i
);
1046 Rectangle
aRect( pClone
->GetSnapRect() );
1054 aOffset
.Height() = (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2;
1058 aOffset
.Height() = aMaxSizeLog
.Height() - aRect
.GetHeight();
1062 aOffset
.Width() = (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2;
1066 aOffset
.Width() = (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2;
1067 aOffset
.Height() = (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2;
1071 aOffset
.Width() = (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2;
1072 aOffset
.Height() = aMaxSizeLog
.Height() - aRect
.GetHeight();
1076 aOffset
.Width() = aMaxSizeLog
.Width() - aRect
.GetWidth();
1080 aOffset
.Width() = aMaxSizeLog
.Width() - aRect
.GetWidth();
1081 aOffset
.Height() = (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2;
1085 aOffset
.Width() = aMaxSizeLog
.Width() - aRect
.GetWidth();
1086 aOffset
.Height() = aMaxSizeLog
.Height() - aRect
.GetHeight();
1090 // Unfortunately, SetSnapRect is not implemented for ellipses !!!
1091 Point
aMovePt( aWindowCenter
+ Point( aOffset
.Width(), aOffset
.Height() ) - aRect
.TopLeft() );
1092 Size
aMoveSize( aMovePt
.X(), aMovePt
.Y() );
1093 pClone
->NbcMove( aMoveSize
);
1096 // #i42894# Caution(!) variable pPage looks right, but it is a page from the local
1097 // document the dialog is using (!), so get the target page from the target view
1098 SdPage
* pTargetSdPage
= dynamic_cast< SdPage
* >(rView
.GetSdrPageView() ? rView
.GetSdrPageView()->GetPage() : 0);
1102 // create animation group
1103 SdrObjGroup
* pGroup
= new SdrObjGroup
;
1104 SdrObjList
* pObjList
= pGroup
->GetSubList();
1106 for (size_t i
= 0; i
< nCount
; ++i
)
1108 // the clone remains in the animatior; we insert a clone of the
1109 // clone into the group
1110 pClone
= pPage
->GetObj(i
);
1111 SdrObject
* pCloneOfClone
= pClone
->Clone();
1112 //SdrObject* pCloneOfClone = pPage->GetObj(i)->Clone();
1113 pObjList
->InsertObject(pCloneOfClone
);
1116 // until now the top left corner of the group is in the window center;
1117 // correct the position by half of the size of the group
1118 aTemp
= aMaxSizeLog
;
1119 aTemp
.Height() = - aTemp
.Height() / 2;
1120 aTemp
.Width() = - aTemp
.Width() / 2;
1121 pGroup
->NbcMove(aTemp
);
1123 // #i42894# create needed SMIL stuff and move child objects to page directly (see
1124 // comments at EffectMigration::CreateAnimatedGroup why this has to be done).
1125 EffectMigration::CreateAnimatedGroup(*pGroup
, *pTargetSdPage
);
1127 // #i42894# if that worked, delete the group again
1128 if(!pGroup
->GetSubList()->GetObjCount())
1135 ClickFirstHdl( this );
1138 void AnimationWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
1140 SfxDockingWindow::DataChanged( rDCEvt
);
1142 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
1149 * ControllerItem for Animator
1151 AnimationControllerItem::AnimationControllerItem(
1153 AnimationWindow
* pAnimWin
,
1154 SfxBindings
* _pBindings
)
1155 : SfxControllerItem( _nId
, *_pBindings
),
1156 pAnimationWin( pAnimWin
)
1160 void AnimationControllerItem::StateChanged( sal_uInt16 nSId
,
1161 SfxItemState eState
, const SfxPoolItem
* pItem
)
1163 if( eState
>= SfxItemState::DEFAULT
&& nSId
== SID_ANIMATOR_STATE
)
1165 const SfxUInt16Item
* pStateItem
= PTR_CAST( SfxUInt16Item
, pItem
);
1166 assert(pStateItem
); //SfxUInt16Item expected
1169 sal_uInt16 nState
= pStateItem
->GetValue();
1170 pAnimationWin
->m_pBtnGetOneObject
->Enable( nState
& 1 );
1171 pAnimationWin
->m_pBtnGetAllObjects
->Enable( nState
& 2 );
1176 } // end of namespace sd
1178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */