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 .
21 #include <svl/eitem.hxx>
22 #include <svl/intitem.hxx>
23 #include <svx/svdograf.hxx>
24 #include <svx/svdogrp.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <sfx2/progress.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <vcl/virdev.hxx>
31 #include <anminfo.hxx>
32 #include <animobjs.hxx>
34 #include <strings.hrc>
35 #include <sdresid.hxx>
37 #include <drawdoc.hxx>
40 #include <ViewShell.hxx>
42 #include <vcl/settings.hxx>
44 #include <EffectMigration.hxx>
48 using namespace ::com::sun::star
;
55 SdDisplay::SdDisplay(vcl::Window
* pWin
)
59 SetMapMode(MapMode(MapUnit::MapPixel
));
60 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
61 SetBackground( Wallpaper( rStyles
.GetFieldColor() ) );
64 SdDisplay::~SdDisplay()
68 void SdDisplay::SetBitmapEx( BitmapEx
const * pBmpEx
)
76 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
77 const Color aFillColor
= rStyles
.GetFieldColor();
78 aBitmapEx
.Erase(aFillColor
);
82 void SdDisplay::Paint( vcl::RenderContext
& /*rRenderContext*/, const ::tools::Rectangle
& )
85 Size aSize
= GetOutputSize();
86 Size aBmpSize
= aBitmapEx
.GetBitmap().GetSizePixel();
87 aBmpSize
.setWidth( static_cast<long>( static_cast<double>(aBmpSize
.Width()) * static_cast<double>(aScale
) ) );
88 aBmpSize
.setHeight( static_cast<long>( static_cast<double>(aBmpSize
.Height()) * static_cast<double>(aScale
) ) );
90 if( aBmpSize
.Width() < aSize
.Width() )
91 aPt
.setX( ( aSize
.Width() - aBmpSize
.Width() ) / 2 );
92 if( aBmpSize
.Height() < aSize
.Height() )
93 aPt
.setY( ( aSize
.Height() - aBmpSize
.Height() ) / 2 );
95 aBitmapEx
.Draw( this, aPt
, aBmpSize
);
98 void SdDisplay::SetScale( const Fraction
& rFrac
)
103 Size
SdDisplay::GetOptimalSize() const
105 return LogicToPixel(Size(147, 87), MapMode(MapUnit::MapAppFont
));
108 void SdDisplay::DataChanged( const DataChangedEvent
& rDCEvt
)
110 Control::DataChanged( rDCEvt
);
112 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
114 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
115 SetBackground( Wallpaper( rStyles
.GetFieldColor() ) );
116 SetDrawMode( GetSettings().GetStyleSettings().GetHighContrastMode()
117 ? sd::OUTPUT_DRAWMODE_CONTRAST
118 : sd::OUTPUT_DRAWMODE_COLOR
);
122 const size_t AnimationWindow::EMPTY_FRAMELIST
= std::numeric_limits
<size_t>::max();
125 * AnimationWindow - FloatingWindow
127 AnimationWindow::AnimationWindow(SfxBindings
* pInBindings
, SfxChildWindow
*pCW
, vcl::Window
* pParent
)
128 : SfxDockingWindow(pInBindings
, pCW
, pParent
,
129 "DockingAnimation", "modules/simpress/ui/dockinganimation.ui")
130 , m_nCurrentFrame(EMPTY_FRAMELIST
)
134 get(m_pBtnFirst
, "first");
135 get(m_pBtnReverse
, "prev");
136 get(m_pBtnStop
, "stop");
137 get(m_pBtnPlay
, "next");
138 get(m_pBtnLast
, "last");
139 get(m_pNumFldBitmap
, "numbitmap");
140 get(m_pTimeField
, "duration");
141 m_pTimeField
->SetDuration(true);
142 m_pTimeField
->EnforceValidValue(true);
143 m_pTimeField
->SetMax(tools::Time(0, 0, 59, 99*tools::Time::nanoPerCenti
));
144 get(m_pLbLoopCount
, "loopcount");
145 get(m_pBtnGetOneObject
, "getone");
146 get(m_pBtnGetAllObjects
, "getall");
147 get(m_pBtnRemoveBitmap
, "delone");
148 get(m_pBtnRemoveAll
, "delall");
149 get(m_pFiCount
, "count");
150 get(m_pRbtGroup
, "group");
151 get(m_pRbtBitmap
, "bitmap");
152 get(m_pFtAdjustment
, "alignmentft");
153 get(m_pLbAdjustment
, "alignment");
154 get(m_pBtnCreateGroup
, "create");
156 m_pCtlDisplay
= VclPtr
<SdDisplay
>::Create(get
<Window
>("box"));
157 m_pCtlDisplay
->set_hexpand(true);
158 m_pCtlDisplay
->set_vexpand(true);
159 m_pCtlDisplay
->Show();
161 // create new document with page
162 pMyDoc
.reset( new SdDrawDocument(DocumentType::Impress
, nullptr) );
163 SdPage
* pPage
= pMyDoc
->AllocSdPage(false);
164 pMyDoc
->InsertPage(pPage
);
166 pControllerItem
.reset( new AnimationControllerItem( SID_ANIMATOR_STATE
, this, pInBindings
) );
168 // as long as not in the resource
169 m_pTimeField
->SetFormat( TimeFieldFormat::F_SEC_CS
);
171 m_pBtnFirst
->SetClickHdl( LINK( this, AnimationWindow
, ClickFirstHdl
) );
172 m_pBtnReverse
->SetClickHdl( LINK( this, AnimationWindow
, ClickPlayHdl
) );
173 m_pBtnStop
->SetClickHdl( LINK( this, AnimationWindow
, ClickStopHdl
) );
174 m_pBtnPlay
->SetClickHdl( LINK( this, AnimationWindow
, ClickPlayHdl
) );
175 m_pBtnLast
->SetClickHdl( LINK( this, AnimationWindow
, ClickLastHdl
) );
177 m_pBtnGetOneObject
->SetClickHdl( LINK( this, AnimationWindow
, ClickGetObjectHdl
) );
178 m_pBtnGetAllObjects
->SetClickHdl( LINK( this, AnimationWindow
, ClickGetObjectHdl
) );
179 m_pBtnRemoveBitmap
->SetClickHdl( LINK( this, AnimationWindow
, ClickRemoveBitmapHdl
) );
180 m_pBtnRemoveAll
->SetClickHdl( LINK( this, AnimationWindow
, ClickRemoveBitmapHdl
) );
182 m_pRbtGroup
->SetClickHdl( LINK( this, AnimationWindow
, ClickRbtHdl
) );
183 m_pRbtBitmap
->SetClickHdl( LINK( this, AnimationWindow
, ClickRbtHdl
) );
184 m_pBtnCreateGroup
->SetClickHdl( LINK( this, AnimationWindow
, ClickCreateGroupHdl
) );
185 m_pNumFldBitmap
->SetModifyHdl( LINK( this, AnimationWindow
, ModifyBitmapHdl
) );
186 m_pTimeField
->SetModifyHdl( LINK( this, AnimationWindow
, ModifyTimeHdl
) );
189 m_pCtlDisplay
->SetBorderStyle(WindowBorderStyle::MONO
);
191 SetMinOutputSizePixel(GetOptimalSize());
195 // the animator is empty; no animation group can be created
196 m_pBtnCreateGroup
->Disable();
199 AnimationWindow::~AnimationWindow()
204 void AnimationWindow::dispose()
206 pControllerItem
.reset();
209 m_nCurrentFrame
= EMPTY_FRAMELIST
;
214 m_pCtlDisplay
.disposeAndClear();
216 m_pBtnReverse
.clear();
220 m_pNumFldBitmap
.clear();
221 m_pTimeField
.clear();
222 m_pLbLoopCount
.clear();
223 m_pBtnGetOneObject
.clear();
224 m_pBtnGetAllObjects
.clear();
225 m_pBtnRemoveBitmap
.clear();
226 m_pBtnRemoveAll
.clear();
229 m_pRbtBitmap
.clear();
230 m_pFtAdjustment
.clear();
231 m_pLbAdjustment
.clear();
232 m_pBtnCreateGroup
.clear();
233 SfxDockingWindow::dispose();
236 IMPL_LINK_NOARG(AnimationWindow
, ClickFirstHdl
, Button
*, void)
238 m_nCurrentFrame
= (m_FrameList
.empty()) ? EMPTY_FRAMELIST
: 0;
242 IMPL_LINK_NOARG(AnimationWindow
, ClickStopHdl
, Button
*, void)
247 IMPL_LINK( AnimationWindow
, ClickPlayHdl
, Button
*, p
, void )
249 ScopeLockGuard
aGuard( maPlayLock
);
252 bool bDisableCtrls
= false;
253 size_t const nCount
= m_FrameList
.size();
254 bool bReverse
= p
== m_pBtnReverse
;
256 // it is difficult to find it later on
257 bool bRbtGroupEnabled
= m_pRbtGroup
->IsEnabled();
258 bool bBtnGetAllObjectsEnabled
= m_pBtnGetAllObjects
->IsEnabled();
259 bool bBtnGetOneObjectEnabled
= m_pBtnGetOneObject
->IsEnabled();
261 // calculate overall time
262 tools::Time
aTime( 0 );
264 if( m_pRbtBitmap
->IsChecked() )
266 for (size_t i
= 0; i
< nCount
; ++i
)
268 aTime
+= m_FrameList
[i
].second
;
270 nFullTime
= aTime
.GetMSFromTime();
274 nFullTime
= nCount
* 100;
275 aTime
.MakeTimeFromMS( nFullTime
);
278 // StatusBarManager from 1 second
279 std::unique_ptr
<SfxProgress
> pProgress
;
280 if( nFullTime
>= 1000 )
282 bDisableCtrls
= true;
283 m_pBtnStop
->Enable();
284 m_pBtnStop
->Update();
285 OUString
const aStr("Animator:"); // here we should think about something smart
286 pProgress
.reset(new SfxProgress( nullptr, aStr
, nFullTime
));
289 sal_uLong nTmpTime
= 0;
291 bool bCount
= i
< nCount
;
296 while( bCount
&& bMovie
)
298 // make list and view consistent
299 assert(i
< m_FrameList
.size());
302 UpdateControl(bDisableCtrls
);
304 if( m_pRbtBitmap
->IsChecked() )
306 tools::Time
const & rTime
= m_FrameList
[i
].second
;
308 m_pTimeField
->SetTime( rTime
);
309 sal_uLong nTime
= rTime
.GetMSFromTime();
311 WaitInEffect( nTime
, nTmpTime
, pProgress
.get() );
316 WaitInEffect( 100, nTmpTime
, pProgress
.get() );
338 // Move i back into valid range.
344 // to re-enable the controls
348 assert(i
== m_nCurrentFrame
);
355 m_pBtnStop
->Disable();
358 m_pRbtGroup
->Enable( bRbtGroupEnabled
);
359 m_pBtnGetAllObjects
->Enable( bBtnGetAllObjectsEnabled
);
360 m_pBtnGetOneObject
->Enable( bBtnGetOneObjectEnabled
);
363 IMPL_LINK_NOARG(AnimationWindow
, ClickLastHdl
, Button
*, void)
366 (m_FrameList
.empty()) ? EMPTY_FRAMELIST
: m_FrameList
.size() - 1 ;
370 IMPL_LINK( AnimationWindow
, ClickRbtHdl
, Button
*, p
, void )
372 if (m_FrameList
.empty() || p
== m_pRbtGroup
|| m_pRbtGroup
->IsChecked())
374 m_pTimeField
->SetText( OUString() );
375 m_pTimeField
->Enable( false );
376 m_pLbLoopCount
->Enable( false );
378 else if( p
== m_pRbtBitmap
|| m_pRbtBitmap
->IsChecked() )
380 sal_uLong n
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue());
383 tools::Time
const & rTime
= m_FrameList
[n
- 1].second
;
384 m_pTimeField
->SetTime( rTime
);
386 m_pTimeField
->Enable();
387 m_pLbLoopCount
->Enable();
391 IMPL_LINK( AnimationWindow
, ClickGetObjectHdl
, Button
*, pBtn
, void )
393 bAllObjects
= pBtn
== m_pBtnGetAllObjects
;
395 // Code now in AddObj()
396 SfxBoolItem
aItem( SID_ANIMATOR_ADD
, true );
398 GetBindings().GetDispatcher()->ExecuteList(
399 SID_ANIMATOR_ADD
, SfxCallMode::SLOT
| SfxCallMode::RECORD
, { &aItem
});
402 IMPL_LINK( AnimationWindow
, ClickRemoveBitmapHdl
, Button
*, pBtn
, void )
404 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PageKind::Standard
);
407 // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access
408 if (pBtn
== m_pBtnRemoveBitmap
&& EMPTY_FRAMELIST
!= m_nCurrentFrame
)
410 m_FrameList
.erase(m_FrameList
.begin() + m_nCurrentFrame
);
412 pObject
= pPage
->GetObj(m_nCurrentFrame
);
413 // Through acquisition of the AnimatedGIFs, objects does not need to
417 pObject
= pPage
->RemoveObject(m_nCurrentFrame
);
418 DBG_ASSERT(pObject
, "Clone not found during deletion");
419 SdrObject::Free( pObject
);
420 pPage
->RecalcObjOrdNums();
423 if (m_nCurrentFrame
>= m_FrameList
.size())
425 // tdf#95298 last frame was deleted, try to use the one before it or go on empty state
426 m_nCurrentFrame
= m_FrameList
.empty() ? EMPTY_FRAMELIST
: m_FrameList
.size() - 1;
429 else // delete everything
431 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
432 VclMessageType::Warning
, VclButtonsType::YesNo
,
433 SdResId(STR_ASK_DELETE_ALL_PICTURES
)));
434 short nReturn
= xWarn
->run();
436 if( nReturn
== RET_YES
)
439 for (size_t i
= m_FrameList
.size(); i
> 0; )
442 pObject
= pPage
->GetObj( i
);
445 pObject
= pPage
->RemoveObject( i
);
446 DBG_ASSERT(pObject
, "Clone not found during deletion");
447 SdrObject::Free( pObject
);
448 //pPage->RecalcObjOrdNums();
452 m_nCurrentFrame
= EMPTY_FRAMELIST
;
456 // can we create a animation group
457 if (m_FrameList
.empty())
459 m_pBtnCreateGroup
->Disable();
460 // if previous disabled by acquisition of AnimatedGIFs:
461 //m_pRbtBitmap->Enable();
462 m_pRbtGroup
->Enable();
465 // calculate and set zoom for DisplayWin
466 Fraction
aFrac(GetScale());
467 m_pCtlDisplay
->SetScale(aFrac
);
472 IMPL_LINK_NOARG(AnimationWindow
, ClickCreateGroupHdl
, Button
*, void)
474 // Code now in CreatePresObj()
475 SfxBoolItem
aItem( SID_ANIMATOR_CREATE
, true );
477 GetBindings().GetDispatcher()->ExecuteList(SID_ANIMATOR_CREATE
,
478 SfxCallMode::SLOT
| SfxCallMode::RECORD
, { &aItem
});
481 IMPL_LINK_NOARG(AnimationWindow
, ModifyBitmapHdl
, Edit
&, void)
483 sal_uLong nBmp
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue());
485 if (nBmp
> m_FrameList
.size())
487 nBmp
= m_FrameList
.size();
490 m_nCurrentFrame
= nBmp
- 1;
495 IMPL_LINK_NOARG(AnimationWindow
, ModifyTimeHdl
, Edit
&, void)
497 sal_uLong nPos
= static_cast<sal_uLong
>(m_pNumFldBitmap
->GetValue() - 1);
499 tools::Time
& rTime
= m_FrameList
[nPos
].second
;
501 rTime
= m_pTimeField
->GetTime();
504 void AnimationWindow::UpdateControl(bool const bDisableCtrls
)
506 // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access
507 if (!m_FrameList
.empty() && EMPTY_FRAMELIST
!= m_nCurrentFrame
)
509 BitmapEx
& rBmp(m_FrameList
[m_nCurrentFrame
].first
);
511 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PageKind::Standard
);
512 SdrObject
*const pObject
= pPage
->GetObj(m_nCurrentFrame
);
515 ScopedVclPtrInstance
< VirtualDevice
> pVD
;
516 ::tools::Rectangle
aObjRect( pObject
->GetCurrentBoundRect() );
517 Size
aObjSize( aObjRect
.GetSize() );
518 Point
aOrigin( Point( -aObjRect
.Left(), -aObjRect
.Top() ) );
519 MapMode
aMap( pVD
->GetMapMode() );
520 aMap
.SetMapUnit( MapUnit::Map100thMM
);
521 aMap
.SetOrigin( aOrigin
);
522 pVD
->SetMapMode( aMap
);
523 pVD
->SetOutputSize( aObjSize
);
524 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
525 pVD
->SetBackground( Wallpaper( rStyles
.GetFieldColor() ) );
526 pVD
->SetDrawMode( rStyles
.GetHighContrastMode()
527 ? sd::OUTPUT_DRAWMODE_CONTRAST
528 : sd::OUTPUT_DRAWMODE_COLOR
);
530 pObject
->SingleObjectPainter( *pVD
);
531 rBmp
= pVD
->GetBitmapEx( aObjRect
.TopLeft(), aObjSize
);
534 m_pCtlDisplay
->SetBitmapEx(&rBmp
);
538 m_pCtlDisplay
->SetBitmapEx(nullptr);
540 m_pCtlDisplay
->Invalidate();
541 m_pCtlDisplay
->Update();
543 m_pFiCount
->SetText(OUString::number(
544 m_FrameList
.size()));
546 if (!m_FrameList
.empty() && !bMovie
)
548 size_t nIndex
= m_nCurrentFrame
+ 1;
549 m_pNumFldBitmap
->SetValue(nIndex
);
551 // if there is at least 1 object in the list
552 m_pBtnFirst
->Enable();
553 m_pBtnReverse
->Enable();
554 m_pBtnPlay
->Enable();
555 m_pBtnLast
->Enable();
556 m_pNumFldBitmap
->Enable();
557 m_pTimeField
->Enable();
558 m_pLbLoopCount
->Enable();
559 m_pBtnRemoveBitmap
->Enable();
560 m_pBtnRemoveAll
->Enable();
564 // if no object is in the list
565 m_pBtnFirst
->Enable( false );
566 m_pBtnReverse
->Enable( false );
567 m_pBtnPlay
->Enable( false );
568 m_pBtnLast
->Enable( false );
569 m_pNumFldBitmap
->Enable( false );
570 m_pTimeField
->Enable( false );
571 m_pLbLoopCount
->Enable( false );
572 m_pBtnRemoveBitmap
->Enable( false );
573 m_pBtnRemoveAll
->Enable( false );
576 if( bMovie
&& bDisableCtrls
)
578 m_pBtnGetOneObject
->Enable( false );
579 m_pBtnGetAllObjects
->Enable( false );
580 m_pRbtGroup
->Enable( false );
581 m_pRbtBitmap
->Enable( false );
582 m_pBtnCreateGroup
->Enable( false );
583 m_pFtAdjustment
->Enable( false );
584 m_pLbAdjustment
->Enable( false );
588 // enable 'group object' only if it is not a Animated GIF
589 if (m_FrameList
.empty())
591 m_pRbtGroup
->Enable();
594 m_pRbtBitmap
->Enable();
595 m_pBtnCreateGroup
->Enable(!m_FrameList
.empty());
596 m_pFtAdjustment
->Enable();
597 m_pLbAdjustment
->Enable();
600 ClickRbtHdl( nullptr );
603 void AnimationWindow::ResetAttrs()
605 m_pRbtGroup
->Check();
606 m_pLbAdjustment
->SelectEntryPos( BA_CENTER
);
608 m_pLbLoopCount
->SelectEntryPos( m_pLbLoopCount
->GetEntryCount() - 1);
613 void AnimationWindow::WaitInEffect( sal_uLong nMilliSeconds
, sal_uLong nTime
,
614 SfxProgress
* pProgress
) const
616 sal_uInt64 aEnd
= tools::Time::GetSystemTicks() + nMilliSeconds
;
617 sal_uInt64 aCurrent
= tools::Time::GetSystemTicks();
618 while (aCurrent
< aEnd
)
620 aCurrent
= tools::Time::GetSystemTicks();
623 pProgress
->SetState( nTime
+ nMilliSeconds
+ aCurrent
- aEnd
);
625 Application::Reschedule();
632 Fraction
AnimationWindow::GetScale()
635 size_t const nCount
= m_FrameList
.size();
639 for (size_t i
= 0; i
< nCount
; i
++)
641 BitmapEx
const & rBitmap
= m_FrameList
[i
].first
;
642 Size
aTempSize( rBitmap
.GetBitmap().GetSizePixel() );
643 aBmpSize
.setWidth( std::max( aBmpSize
.Width(), aTempSize
.Width() ) );
644 aBmpSize
.setHeight( std::max( aBmpSize
.Height(), aTempSize
.Height() ) );
647 aBmpSize
.AdjustWidth(10 );
648 aBmpSize
.AdjustHeight(10 );
650 Size
aDisplaySize(m_pCtlDisplay
->GetOutputSize());
652 aFrac
= Fraction( std::min( static_cast<double>(aDisplaySize
.Width()) / static_cast<double>(aBmpSize
.Width()),
653 static_cast<double>(aDisplaySize
.Height()) / static_cast<double>(aBmpSize
.Height()) ) );
658 void AnimationWindow::Resize()
660 SfxDockingWindow::Resize();
661 Fraction
aFrac(GetScale());
662 m_pCtlDisplay
->SetScale(aFrac
);
665 bool AnimationWindow::Close()
667 if( maPlayLock
.isLocked() )
673 SfxBoolItem
aItem( SID_ANIMATION_OBJECTS
, false );
675 GetBindings().GetDispatcher()->ExecuteList(
676 SID_ANIMATION_OBJECTS
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
679 SfxDockingWindow::Close();
685 void AnimationWindow::AddObj (::sd::View
& rView
)
687 // finish text entry mode to ensure that bitmap is identical with object
688 if( rView
.IsTextEdit() )
689 rView
.SdrEndTextEdit();
691 // clone object(s) and insert the clone(s) into the list
692 const SdrMarkList
& rMarkList
= rView
.GetMarkedObjectList();
693 const size_t nMarkCount
= rMarkList
.GetMarkCount();
694 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PageKind::Standard
);
695 const size_t nCloneCount
= pPage
->GetObjCount();
700 // If it is ONE animation object or one group object, which was
701 // 'individually taken', we insert the objects separately
702 bool bAnimObj
= false;
703 if( nMarkCount
== 1 )
705 SdrMark
* pMark
= rMarkList
.GetMark(0);
706 SdrObject
* pObject
= pMark
->GetMarkedSdrObj();
707 SdAnimationInfo
* pAnimInfo
= SdDrawDocument::GetAnimationInfo( pObject
);
708 SdrInventor nInv
= pObject
->GetObjInventor();
709 sal_uInt16 nId
= pObject
->GetObjIdentifier();
711 // Animated Bitmap (GIF)
712 if( nInv
== SdrInventor::Default
&& nId
== OBJ_GRAF
&& static_cast<SdrGrafObj
*>( pObject
)->IsAnimated() )
714 const SdrGrafObj
* pGrafObj
= static_cast<SdrGrafObj
*>(pObject
);
715 Graphic
aGraphic( pGrafObj
->GetTransformedGraphic() );
716 sal_uInt16 nCount
= 0;
718 if( aGraphic
.IsAnimated() )
719 nCount
= aGraphic
.GetAnimation().Count();
723 const Animation
aAnimation( aGraphic
.GetAnimation() );
725 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
727 const AnimationBitmap
& rAnimationBitmap
= aAnimation
.Get( i
);
732 sal_uInt32 nLoopCount
= aAnimation
.GetLoopCount();
734 if( !nLoopCount
) // endless
735 m_pLbLoopCount
->SelectEntryPos( m_pLbLoopCount
->GetEntryCount() - 1);
737 m_pLbLoopCount
->SelectEntry(OUString::number( nLoopCount
) );
740 long nTime
= rAnimationBitmap
.mnWait
;
741 ::tools::Time
aTime( 0, 0, nTime
/ 100, nTime
% 100 );
742 size_t nIndex
= m_nCurrentFrame
+ 1;
744 m_FrameList
.begin() + nIndex
,
745 ::std::make_pair(rAnimationBitmap
.maBitmapEx
, aTime
));
747 // increment => next one inserted after this one
750 // if a animated GIF is taken, only such one can be created
751 m_pRbtBitmap
->Check();
752 m_pRbtGroup
->Enable( false );
756 else if( bAllObjects
|| ( pAnimInfo
&& pAnimInfo
->mbIsMovie
) )
759 SdrObjList
* pObjList
= static_cast<SdrObjGroup
*>(pObject
)->GetSubList();
761 for( size_t nObject
= 0; nObject
< pObjList
->GetObjCount(); ++nObject
)
763 SdrObject
* pSnapShot(pObjList
->GetObj(nObject
));
764 BitmapEx
aBitmapEx(SdrExchangeView::GetObjGraphic(*pSnapShot
).GetBitmapEx());
765 size_t nIndex
= m_nCurrentFrame
+ 1;
767 m_FrameList
.begin() + nIndex
,
768 ::std::make_pair(aBitmapEx
, m_pTimeField
->GetTime()));
770 // increment => next one inserted after this one
775 pSnapShot
->CloneSdrObject(pPage
->getSdrModelFromSdrPage()),
781 // also one single animated object
782 if( !bAnimObj
&& !( bAllObjects
&& nMarkCount
> 1 ) )
784 BitmapEx
aBitmapEx(rView
.GetAllMarkedGraphic().GetBitmapEx());
786 ::tools::Time
aTime( m_pTimeField
->GetTime() );
788 size_t nIndex
= m_nCurrentFrame
+ 1;
790 m_FrameList
.begin() + nIndex
,
791 ::std::make_pair(aBitmapEx
, aTime
));
795 if( nMarkCount
== 1 && !bAnimObj
)
797 SdrMark
* pMark
= rMarkList
.GetMark(0);
798 SdrObject
* pObject
= pMark
->GetMarkedSdrObj();
799 SdrObject
* pClone(pObject
->CloneSdrObject(pPage
->getSdrModelFromSdrPage()));
800 size_t nIndex
= m_nCurrentFrame
+ 1;
801 pPage
->InsertObject(pClone
, nIndex
);
803 // several objects: group the clones
804 else if (nMarkCount
> 1)
806 // take objects separately
809 for( size_t nObject
= 0; nObject
< nMarkCount
; ++nObject
)
812 SdrObject
* pObject(rMarkList
.GetMark(nObject
)->GetMarkedSdrObj());
813 BitmapEx
aBitmapEx(SdrExchangeView::GetObjGraphic(*pObject
).GetBitmapEx());
814 size_t nIndex
= m_nCurrentFrame
+ 1;
816 m_FrameList
.begin() + nIndex
,
817 ::std::make_pair(aBitmapEx
, m_pTimeField
->GetTime()));
819 // increment => next one inserted after this one
823 pObject
->CloneSdrObject(pPage
->getSdrModelFromSdrPage()),
826 bAnimObj
= true; // that we don't change again
830 SdrObjGroup
* pCloneGroup
= new SdrObjGroup(rView
.getSdrModelFromSdrView());
831 SdrObjList
* pObjList
= pCloneGroup
->GetSubList();
833 for (size_t nObject
= 0; nObject
< nMarkCount
; ++nObject
)
835 pObjList
->InsertObject(
836 rMarkList
.GetMark(nObject
)->GetMarkedSdrObj()->CloneSdrObject(
837 pPage
->getSdrModelFromSdrPage()));
840 size_t nIndex
= m_nCurrentFrame
+ 1;
841 pPage
->InsertObject(pCloneGroup
, nIndex
);
850 // if there was nothing in the animator before but now is something
851 // there, we can create a animation group
852 if (nCloneCount
== 0 && !m_FrameList
.empty())
854 m_pBtnCreateGroup
->Enable();
857 // calculate and set zoom for DisplayWin
858 Fraction
aFrac( GetScale() );
859 m_pCtlDisplay
->SetScale(aFrac
);
864 void AnimationWindow::CreateAnimObj (::sd::View
& rView
)
866 vcl::Window
* pOutWin
= static_cast< vcl::Window
*>(rView
.GetFirstOutputDevice()); // GetWin( 0 );
867 DBG_ASSERT( pOutWin
, "Window does not exist!" );
869 // find window center
870 const MapMode
aMap100( MapUnit::Map100thMM
);
873 Size
aTemp( pOutWin
->GetOutputSizePixel() );
874 const Point
aWindowCenter( pOutWin
->PixelToLogic( Point( aTemp
.Width() >> 1, aTemp
.Height() >> 1 ) ) );
875 const OutputDevice
* pDefDev
= Application::GetDefaultDevice();
876 const size_t nCount
= m_FrameList
.size();
877 BitmapAdjustment eBA
= static_cast<BitmapAdjustment
>(m_pLbAdjustment
->GetSelectedEntryPos());
879 // find biggest bitmap
880 for (size_t i
= 0; i
< nCount
; ++i
)
882 const BitmapEx
& rBmpEx
= m_FrameList
[i
].first
;
883 const Graphic
aGraphic( rBmpEx
);
885 const Size
aTmpSizePix( rBmpEx
.GetSizePixel() );
887 if ( aGraphic
.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
888 aTmpSizeLog
= pDefDev
->PixelToLogic( aGraphic
.GetPrefSize(), aMap100
);
890 aTmpSizeLog
= OutputDevice::LogicToLogic( aGraphic
.GetPrefSize(), aGraphic
.GetPrefMapMode(), aMap100
);
892 aMaxSizeLog
.setWidth( std::max( aMaxSizeLog
.Width(), aTmpSizeLog
.Width() ) );
893 aMaxSizeLog
.setHeight( std::max( aMaxSizeLog
.Height(), aTmpSizeLog
.Height() ) );
895 aMaxSizePix
.setWidth( std::max( aMaxSizePix
.Width(), aTmpSizePix
.Width() ) );
896 aMaxSizePix
.setHeight( std::max( aMaxSizePix
.Height(), aTmpSizePix
.Height() ) );
899 SdrPageView
* pPV
= rView
.GetSdrPageView();
901 if( m_pRbtBitmap
->IsChecked() )
903 // create bitmap group (Animated GIF)
904 Animation aAnimation
;
907 for (size_t i
= 0; i
< nCount
; ++i
)
909 tools::Time
const & rTime
= m_FrameList
[i
].second
;
910 long nTime
= rTime
.GetNanoSec();
911 nTime
+= rTime
.GetSec() * 100;
913 BitmapEx
const & rBitmapEx
= m_FrameList
[i
].first
;
915 // calculate offset for the specified direction
916 const Size
aBitmapSize( rBitmapEx
.GetSizePixel() );
924 aPt
.setY( (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1 );
928 aPt
.setY( aMaxSizePix
.Height() - aBitmapSize
.Height() );
932 aPt
.setX( (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1 );
936 aPt
.setX( (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1 );
937 aPt
.setY( (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1 );
941 aPt
.setX( (aMaxSizePix
.Width() - aBitmapSize
.Width()) >> 1 );
942 aPt
.setY( aMaxSizePix
.Height() - aBitmapSize
.Height() );
946 aPt
.setX( aMaxSizePix
.Width() - aBitmapSize
.Width() );
950 aPt
.setX( aMaxSizePix
.Width() - aBitmapSize
.Width() );
951 aPt
.setY( (aMaxSizePix
.Height() - aBitmapSize
.Height()) >> 1 );
955 aPt
.setX( aMaxSizePix
.Width() - aBitmapSize
.Width() );
956 aPt
.setY( aMaxSizePix
.Height() - aBitmapSize
.Height() );
961 // find LoopCount (number of passes)
962 AnimationBitmap aAnimationBitmap
;
963 sal_uInt32 nLoopCount
= 0;
964 sal_Int32 nPos
= m_pLbLoopCount
->GetSelectedEntryPos();
966 if( nPos
!= LISTBOX_ENTRY_NOTFOUND
&& nPos
!= m_pLbLoopCount
->GetEntryCount() - 1 ) // endless
967 nLoopCount
= m_pLbLoopCount
->GetSelectedEntry().toUInt32();
969 aAnimationBitmap
.maBitmapEx
= rBitmapEx
;
970 aAnimationBitmap
.maPositionPixel
= aPt
;
971 aAnimationBitmap
.maSizePixel
= aBitmapSize
;
972 aAnimationBitmap
.mnWait
= nTime
;
973 aAnimationBitmap
.meDisposal
= Disposal::Back
;
974 aAnimationBitmap
.mbUserInput
= false;
976 aAnimation
.Insert( aAnimationBitmap
);
977 aAnimation
.SetDisplaySizePixel( aMaxSizePix
);
978 aAnimation
.SetLoopCount( nLoopCount
);
981 SdrGrafObj
* pGrafObj
= new SdrGrafObj(
982 rView
.getSdrModelFromSdrView(),
983 Graphic(aAnimation
));
984 const Point
aOrg( aWindowCenter
.X() - ( aMaxSizeLog
.Width() >> 1 ), aWindowCenter
.Y() - ( aMaxSizeLog
.Height() >> 1 ) );
986 pGrafObj
->SetLogicRect( ::tools::Rectangle( aOrg
, aMaxSizeLog
) );
987 rView
.InsertObjectAtView( pGrafObj
, *pPV
, SdrInsertFlags::SETDEFLAYER
);
991 // calculate offset for the specified direction
993 SdrObject
* pClone
= nullptr;
994 SdPage
* pPage
= pMyDoc
->GetSdPage(0, PageKind::Standard
);
996 for (size_t i
= 0; i
< nCount
; ++i
)
998 pClone
= pPage
->GetObj(i
);
999 ::tools::Rectangle
aRect( pClone
->GetSnapRect() );
1007 aOffset
.setHeight( (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2 );
1011 aOffset
.setHeight( aMaxSizeLog
.Height() - aRect
.GetHeight() );
1015 aOffset
.setWidth( (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2 );
1019 aOffset
.setWidth( (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2 );
1020 aOffset
.setHeight( (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2 );
1024 aOffset
.setWidth( (aMaxSizeLog
.Width() - aRect
.GetWidth()) / 2 );
1025 aOffset
.setHeight( aMaxSizeLog
.Height() - aRect
.GetHeight() );
1029 aOffset
.setWidth( aMaxSizeLog
.Width() - aRect
.GetWidth() );
1033 aOffset
.setWidth( aMaxSizeLog
.Width() - aRect
.GetWidth() );
1034 aOffset
.setHeight( (aMaxSizeLog
.Height() - aRect
.GetHeight()) / 2 );
1038 aOffset
.setWidth( aMaxSizeLog
.Width() - aRect
.GetWidth() );
1039 aOffset
.setHeight( aMaxSizeLog
.Height() - aRect
.GetHeight() );
1043 // Unfortunately, SetSnapRect is not implemented for ellipses !!!
1044 Point
aMovePt( aWindowCenter
+ Point( aOffset
.Width(), aOffset
.Height() ) - aRect
.TopLeft() );
1045 Size
aMoveSize( aMovePt
.X(), aMovePt
.Y() );
1046 pClone
->NbcMove( aMoveSize
);
1049 // #i42894# Caution(!) variable pPage looks right, but it is a page from the local
1050 // document the dialog is using (!), so get the target page from the target view
1051 SdPage
* pTargetSdPage
= dynamic_cast< SdPage
* >(rView
.GetSdrPageView() ? rView
.GetSdrPageView()->GetPage() : nullptr);
1055 // create animation group
1056 SdrObjGroup
* pGroup
= new SdrObjGroup(rView
.getSdrModelFromSdrView());
1057 SdrObjList
* pObjList
= pGroup
->GetSubList();
1059 for (size_t i
= 0; i
< nCount
; ++i
)
1061 // the clone remains in the animation; we insert a clone of the
1062 // clone into the group
1063 pClone
= pPage
->GetObj(i
);
1064 SdrObject
* pCloneOfClone(pClone
->CloneSdrObject(pPage
->getSdrModelFromSdrPage()));
1065 //SdrObject* pCloneOfClone = pPage->GetObj(i)->Clone();
1066 pObjList
->InsertObject(pCloneOfClone
);
1069 // until now the top left corner of the group is in the window center;
1070 // correct the position by half of the size of the group
1071 aTemp
= aMaxSizeLog
;
1072 aTemp
.setHeight( - aTemp
.Height() / 2 );
1073 aTemp
.setWidth( - aTemp
.Width() / 2 );
1074 pGroup
->NbcMove(aTemp
);
1076 // #i42894# create needed SMIL stuff and move child objects to page directly (see
1077 // comments at EffectMigration::CreateAnimatedGroup why this has to be done).
1078 EffectMigration::CreateAnimatedGroup(*pGroup
, *pTargetSdPage
);
1080 // #i42894# if that worked, delete the group again
1081 if(!pGroup
->GetSubList()->GetObjCount())
1083 // always use SdrObject::Free(...) for SdrObjects (!)
1084 SdrObject
* pTemp(pGroup
);
1085 SdrObject::Free(pTemp
);
1090 ClickFirstHdl( nullptr );
1093 void AnimationWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
1095 SfxDockingWindow::DataChanged( rDCEvt
);
1097 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
1104 * ControllerItem for Animator
1106 AnimationControllerItem::AnimationControllerItem(
1108 AnimationWindow
* pAnimWin
,
1109 SfxBindings
* _pBindings
)
1110 : SfxControllerItem( _nId
, *_pBindings
),
1111 pAnimationWin( pAnimWin
)
1115 void AnimationControllerItem::StateChanged( sal_uInt16 nSId
,
1116 SfxItemState eState
, const SfxPoolItem
* pItem
)
1118 if( eState
>= SfxItemState::DEFAULT
&& nSId
== SID_ANIMATOR_STATE
)
1120 const SfxUInt16Item
* pStateItem
= dynamic_cast< const SfxUInt16Item
*>( pItem
);
1121 assert(pStateItem
); //SfxUInt16Item expected
1124 sal_uInt16 nState
= pStateItem
->GetValue();
1125 pAnimationWin
->m_pBtnGetOneObject
->Enable( nState
& 1 );
1126 pAnimationWin
->m_pBtnGetAllObjects
->Enable( nState
& 2 );
1131 } // end of namespace sd
1133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */