/src/libreoffice/sd/source/ui/dlg/animobjs.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <time.h> |
21 | | #include <svl/eitem.hxx> |
22 | | #include <svl/intitem.hxx> |
23 | | #include <svx/svdograf.hxx> |
24 | | #include <svx/svdogrp.hxx> |
25 | | #include <svx/svdpagv.hxx> |
26 | | #include <sfx2/dispatch.hxx> |
27 | | #include <sfx2/progress.hxx> |
28 | | #include <vcl/animate/Animation.hxx> |
29 | | #include <vcl/animate/AnimationFrame.hxx> |
30 | | #include <vcl/help.hxx> |
31 | | #include <vcl/svapp.hxx> |
32 | | #include <vcl/weld/Builder.hxx> |
33 | | #include <vcl/weld/MessageDialog.hxx> |
34 | | #include <vcl/weld/weld.hxx> |
35 | | #include <vcl/virdev.hxx> |
36 | | |
37 | | #include <anminfo.hxx> |
38 | | #include <animobjs.hxx> |
39 | | #include <app.hrc> |
40 | | #include <strings.hrc> |
41 | | #include <sdresid.hxx> |
42 | | #include <View.hxx> |
43 | | #include <drawdoc.hxx> |
44 | | #include <sdpage.hxx> |
45 | | |
46 | | #include <ViewShell.hxx> |
47 | | |
48 | | #include <vcl/settings.hxx> |
49 | | |
50 | | #include <EffectMigration.hxx> |
51 | | |
52 | | #include <algorithm> |
53 | | |
54 | | using namespace ::com::sun::star; |
55 | | |
56 | | namespace sd { |
57 | | |
58 | | /** |
59 | | * SdDisplay - Control |
60 | | */ |
61 | | SdDisplay::SdDisplay() |
62 | 0 | : aScale(1, 1) |
63 | 0 | { |
64 | 0 | } |
65 | | |
66 | | SdDisplay::~SdDisplay() |
67 | 0 | { |
68 | 0 | } |
69 | | |
70 | | void SdDisplay::SetBitmap( Bitmap const * pBmp ) |
71 | 0 | { |
72 | 0 | if( pBmp ) |
73 | 0 | { |
74 | 0 | aBitmap = *pBmp; |
75 | 0 | } |
76 | 0 | else |
77 | 0 | { |
78 | 0 | const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings(); |
79 | 0 | const Color aFillColor = rStyles.GetFieldColor(); |
80 | 0 | aBitmap.Erase(aFillColor); |
81 | 0 | } |
82 | 0 | } |
83 | | |
84 | | void SdDisplay::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) |
85 | 0 | { |
86 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::MAPMODE); |
87 | |
|
88 | 0 | rRenderContext.SetMapMode(MapMode(MapUnit::MapPixel)); |
89 | 0 | const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings(); |
90 | 0 | rRenderContext.SetBackground( Wallpaper( rStyles.GetFieldColor() ) ); |
91 | 0 | rRenderContext.Erase(); |
92 | |
|
93 | 0 | Point aPt; |
94 | 0 | Size aSize = GetOutputSizePixel(); |
95 | |
|
96 | 0 | Size aBmpSize = aBitmap.GetSizePixel(); |
97 | 0 | aBmpSize.setWidth( static_cast<::tools::Long>( static_cast<double>(aBmpSize.Width()) * static_cast<double>(aScale) ) ); |
98 | 0 | aBmpSize.setHeight( static_cast<::tools::Long>( static_cast<double>(aBmpSize.Height()) * static_cast<double>(aScale) ) ); |
99 | |
|
100 | 0 | if( aBmpSize.Width() < aSize.Width() ) |
101 | 0 | aPt.setX( ( aSize.Width() - aBmpSize.Width() ) / 2 ); |
102 | 0 | if( aBmpSize.Height() < aSize.Height() ) |
103 | 0 | aPt.setY( ( aSize.Height() - aBmpSize.Height() ) / 2 ); |
104 | |
|
105 | 0 | aBitmap.Draw(&rRenderContext, aPt, aBmpSize); |
106 | 0 | } |
107 | | |
108 | | void SdDisplay::SetScale( const Fraction& rFrac ) |
109 | 0 | { |
110 | 0 | aScale = rFrac; |
111 | 0 | } |
112 | | |
113 | | void SdDisplay::SetDrawingArea(weld::DrawingArea* pDrawingArea) |
114 | 0 | { |
115 | 0 | CustomWidgetController::SetDrawingArea(pDrawingArea); |
116 | 0 | Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(147, 87), MapMode(MapUnit::MapAppFont))); |
117 | 0 | pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); |
118 | 0 | SetOutputSizePixel(aSize); |
119 | 0 | } |
120 | | |
121 | | /** |
122 | | * AnimationWindow - FloatingWindow |
123 | | */ |
124 | | AnimationWindow::AnimationWindow(SfxBindings* pInBindings, SfxChildWindow *pCW, vcl::Window* pParent) |
125 | 0 | : SfxDockingWindow(pInBindings, pCW, pParent, |
126 | 0 | u"DockingAnimation"_ustr, u"modules/simpress/ui/dockinganimation.ui"_ustr) |
127 | 0 | , m_xCtlDisplay(new SdDisplay) |
128 | 0 | , m_xCtlDisplayWin(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, *m_xCtlDisplay)) |
129 | 0 | , m_xBtnFirst(m_xBuilder->weld_button(u"first"_ustr)) |
130 | 0 | , m_xBtnReverse(m_xBuilder->weld_button(u"prev"_ustr)) |
131 | 0 | , m_xBtnStop(m_xBuilder->weld_button(u"stop"_ustr)) |
132 | 0 | , m_xBtnPlay(m_xBuilder->weld_button(u"next"_ustr)) |
133 | 0 | , m_xBtnLast(m_xBuilder->weld_button(u"last"_ustr)) |
134 | 0 | , m_xNumFldBitmap(m_xBuilder->weld_spin_button(u"numbitmap"_ustr)) |
135 | 0 | , m_xTimeField(m_xBuilder->weld_formatted_spin_button(u"duration"_ustr)) |
136 | 0 | , m_xFormatter(new weld::TimeFormatter(*m_xTimeField)) |
137 | 0 | , m_xLbLoopCount(m_xBuilder->weld_combo_box(u"loopcount"_ustr)) |
138 | 0 | , m_xBtnGetOneObject(m_xBuilder->weld_button(u"getone"_ustr)) |
139 | 0 | , m_xBtnGetAllObjects(m_xBuilder->weld_button(u"getall"_ustr)) |
140 | 0 | , m_xBtnRemoveBitmap(m_xBuilder->weld_button(u"delone"_ustr)) |
141 | 0 | , m_xBtnRemoveAll(m_xBuilder->weld_button(u"delall"_ustr)) |
142 | 0 | , m_xFiCount(m_xBuilder->weld_label(u"count"_ustr)) |
143 | 0 | , m_xRbtGroup(m_xBuilder->weld_radio_button(u"group"_ustr)) |
144 | 0 | , m_xRbtBitmap(m_xBuilder->weld_radio_button(u"bitmap"_ustr)) |
145 | 0 | , m_xFtAdjustment(m_xBuilder->weld_label(u"alignmentft"_ustr)) |
146 | 0 | , m_xLbAdjustment(m_xBuilder->weld_combo_box(u"alignment"_ustr)) |
147 | 0 | , m_xBtnCreateGroup(m_xBuilder->weld_button(u"create"_ustr)) |
148 | 0 | , m_xBtnHelp(m_xBuilder->weld_button(u"help"_ustr)) |
149 | 0 | , m_nCurrentFrame(EMPTY_FRAMELIST) |
150 | 0 | , bMovie(false) |
151 | 0 | , bAllObjects(false) |
152 | 0 | { |
153 | 0 | SetText(SdResId(STR_ANIMATION_DIALOG_TITLE)); |
154 | |
|
155 | 0 | m_xFormatter->SetDuration(true); |
156 | 0 | m_xFormatter->SetTimeFormat(TimeFieldFormat::F_SEC_CS); |
157 | 0 | m_xFormatter->EnableEmptyField(false); |
158 | | |
159 | | // create new document with page |
160 | 0 | pMyDoc.reset( new SdDrawDocument(DocumentType::Impress, nullptr) ); |
161 | 0 | rtl::Reference<SdPage> pPage = pMyDoc->AllocSdPage(false); |
162 | 0 | pMyDoc->InsertPage(pPage.get()); |
163 | |
|
164 | 0 | pControllerItem.reset( new AnimationControllerItem( SID_ANIMATOR_STATE, this, pInBindings ) ); |
165 | |
|
166 | 0 | m_xBtnFirst->connect_clicked( LINK( this, AnimationWindow, ClickFirstHdl ) ); |
167 | 0 | m_xBtnReverse->connect_clicked( LINK( this, AnimationWindow, ClickPlayHdl ) ); |
168 | 0 | m_xBtnStop->connect_clicked( LINK( this, AnimationWindow, ClickStopHdl ) ); |
169 | 0 | m_xBtnPlay->connect_clicked( LINK( this, AnimationWindow, ClickPlayHdl ) ); |
170 | 0 | m_xBtnLast->connect_clicked( LINK( this, AnimationWindow, ClickLastHdl ) ); |
171 | |
|
172 | 0 | m_xBtnGetOneObject->connect_clicked( LINK( this, AnimationWindow, ClickGetObjectHdl ) ); |
173 | 0 | m_xBtnGetAllObjects->connect_clicked( LINK( this, AnimationWindow, ClickGetObjectHdl ) ); |
174 | 0 | m_xBtnRemoveBitmap->connect_clicked( LINK( this, AnimationWindow, ClickRemoveBitmapHdl ) ); |
175 | 0 | m_xBtnRemoveAll->connect_clicked( LINK( this, AnimationWindow, ClickRemoveBitmapHdl ) ); |
176 | |
|
177 | 0 | m_xRbtGroup->connect_toggled( LINK( this, AnimationWindow, ClickRbtHdl ) ); |
178 | 0 | m_xRbtBitmap->connect_toggled( LINK( this, AnimationWindow, ClickRbtHdl ) ); |
179 | 0 | m_xBtnCreateGroup->connect_clicked( LINK( this, AnimationWindow, ClickCreateGroupHdl ) ); |
180 | 0 | m_xBtnHelp->connect_clicked( LINK( this, AnimationWindow, ClickHelpHdl ) ); |
181 | 0 | m_xNumFldBitmap->connect_value_changed( LINK( this, AnimationWindow, ModifyBitmapHdl ) ); |
182 | 0 | m_xTimeField->connect_value_changed( LINK( this, AnimationWindow, ModifyTimeHdl ) ); |
183 | |
|
184 | 0 | SetMinOutputSizePixel(GetOptimalSize()); |
185 | |
|
186 | 0 | ResetAttrs(); |
187 | | |
188 | | // the animator is empty; no animation group can be created |
189 | 0 | m_xBtnCreateGroup->set_sensitive(false); |
190 | 0 | } Unexecuted instantiation: sd::AnimationWindow::AnimationWindow(SfxBindings*, SfxChildWindow*, vcl::Window*) Unexecuted instantiation: sd::AnimationWindow::AnimationWindow(SfxBindings*, SfxChildWindow*, vcl::Window*) |
191 | | |
192 | | AnimationWindow::~AnimationWindow() |
193 | 0 | { |
194 | 0 | disposeOnce(); |
195 | 0 | } |
196 | | |
197 | | void AnimationWindow::dispose() |
198 | 0 | { |
199 | 0 | pControllerItem.reset(); |
200 | |
|
201 | 0 | m_FrameList.clear(); |
202 | 0 | m_nCurrentFrame = EMPTY_FRAMELIST; |
203 | | |
204 | | // delete the clones |
205 | 0 | pMyDoc.reset(); |
206 | |
|
207 | 0 | m_xCtlDisplayWin.reset(); |
208 | 0 | m_xCtlDisplay.reset(); |
209 | 0 | m_xBtnFirst.reset(); |
210 | 0 | m_xBtnReverse.reset(); |
211 | 0 | m_xBtnStop.reset(); |
212 | 0 | m_xBtnPlay.reset(); |
213 | 0 | m_xBtnLast.reset(); |
214 | 0 | m_xNumFldBitmap.reset(); |
215 | 0 | m_xFormatter.reset(); |
216 | 0 | m_xTimeField.reset(); |
217 | 0 | m_xLbLoopCount.reset(); |
218 | 0 | m_xBtnGetOneObject.reset(); |
219 | 0 | m_xBtnGetAllObjects.reset(); |
220 | 0 | m_xBtnRemoveBitmap.reset(); |
221 | 0 | m_xBtnRemoveAll.reset(); |
222 | 0 | m_xFiCount.reset(); |
223 | 0 | m_xRbtGroup.reset(); |
224 | 0 | m_xRbtBitmap.reset(); |
225 | 0 | m_xFtAdjustment.reset(); |
226 | 0 | m_xLbAdjustment.reset(); |
227 | 0 | m_xBtnCreateGroup.reset(); |
228 | 0 | m_xBtnHelp.reset(); |
229 | 0 | SfxDockingWindow::dispose(); |
230 | 0 | } |
231 | | |
232 | | IMPL_LINK_NOARG(AnimationWindow, ClickFirstHdl, weld::Button&, void) |
233 | 0 | { |
234 | 0 | m_nCurrentFrame = (m_FrameList.empty()) ? EMPTY_FRAMELIST : 0; |
235 | 0 | UpdateControl(); |
236 | 0 | } |
237 | | |
238 | | IMPL_LINK_NOARG(AnimationWindow, ClickStopHdl, weld::Button&, void) |
239 | 0 | { |
240 | 0 | bMovie = false; |
241 | 0 | } |
242 | | |
243 | | IMPL_LINK( AnimationWindow, ClickPlayHdl, weld::Button&, rButton, void ) |
244 | 0 | { |
245 | 0 | ScopeLockGuard aGuard( maPlayLock ); |
246 | |
|
247 | 0 | bMovie = true; |
248 | 0 | bool bDisableCtrls = false; |
249 | 0 | size_t const nCount = m_FrameList.size(); |
250 | 0 | bool bReverse = &rButton == m_xBtnReverse.get(); |
251 | | |
252 | | // it is difficult to find it later on |
253 | 0 | bool bRbtGroupEnabled = m_xRbtGroup->get_sensitive(); |
254 | 0 | bool bBtnGetAllObjectsEnabled = m_xBtnGetAllObjects->get_sensitive(); |
255 | 0 | bool bBtnGetOneObjectEnabled = m_xBtnGetOneObject->get_sensitive(); |
256 | | |
257 | | // calculate overall time |
258 | 0 | ::tools::Long nFullTime; |
259 | 0 | if( m_xRbtBitmap->get_active() ) |
260 | 0 | { |
261 | 0 | ::tools::Time aTime(::tools::Time::EMPTY); |
262 | 0 | for (size_t i = 0; i < nCount; ++i) |
263 | 0 | { |
264 | 0 | aTime += m_FrameList[i].second; |
265 | 0 | } |
266 | 0 | nFullTime = aTime.GetMSFromTime(); |
267 | 0 | } |
268 | 0 | else |
269 | 0 | { |
270 | 0 | nFullTime = nCount * 100; |
271 | 0 | } |
272 | | |
273 | | // StatusBarManager from 1 second |
274 | 0 | std::unique_ptr<SfxProgress> pProgress; |
275 | 0 | if( nFullTime >= 1000 ) |
276 | 0 | { |
277 | 0 | bDisableCtrls = true; |
278 | 0 | m_xBtnStop->set_sensitive(true); |
279 | 0 | pProgress.reset(new SfxProgress( nullptr, u"Animator:"_ustr, nFullTime )); // "Animator:" here we should think about something smart |
280 | 0 | } |
281 | |
|
282 | 0 | sal_uLong nTmpTime = 0; |
283 | 0 | size_t i = 0; |
284 | 0 | bool bCount = i < nCount; |
285 | 0 | if (bCount) |
286 | 0 | { |
287 | 0 | if( bReverse ) |
288 | 0 | i = nCount - 1; |
289 | |
|
290 | 0 | while (bMovie) |
291 | 0 | { |
292 | | // make list and view consistent |
293 | 0 | assert(i < m_FrameList.size()); |
294 | 0 | m_nCurrentFrame = i; |
295 | |
|
296 | 0 | UpdateControl(bDisableCtrls); |
297 | |
|
298 | 0 | if( m_xRbtBitmap->get_active() ) |
299 | 0 | { |
300 | 0 | ::tools::Time const & rTime = m_FrameList[i].second; |
301 | |
|
302 | 0 | m_xFormatter->SetTime( rTime ); |
303 | 0 | sal_uLong nTime = rTime.GetMSFromTime(); |
304 | |
|
305 | 0 | WaitInEffect( nTime, nTmpTime, pProgress.get() ); |
306 | 0 | nTmpTime += nTime; |
307 | 0 | } |
308 | 0 | else |
309 | 0 | { |
310 | 0 | WaitInEffect( 100, nTmpTime, pProgress.get() ); |
311 | 0 | nTmpTime += 100; |
312 | 0 | } |
313 | 0 | if( bReverse ) |
314 | 0 | { |
315 | 0 | if (i == 0) |
316 | 0 | { |
317 | | // Terminate loop. |
318 | 0 | bCount = false; |
319 | 0 | } |
320 | 0 | else |
321 | 0 | { |
322 | 0 | --i; |
323 | 0 | } |
324 | 0 | } |
325 | 0 | else |
326 | 0 | { |
327 | 0 | i++; |
328 | 0 | if (i >= nCount) |
329 | 0 | { |
330 | | // Terminate loop. |
331 | 0 | bCount = false; |
332 | | // Move i back into valid range. |
333 | 0 | i = nCount - 1; |
334 | 0 | } |
335 | 0 | } |
336 | |
|
337 | 0 | if (!bCount) |
338 | 0 | break; |
339 | 0 | } |
340 | 0 | } |
341 | | |
342 | | // to re-enable the controls |
343 | 0 | bMovie = false; |
344 | 0 | if (nCount > 0) |
345 | 0 | { |
346 | 0 | assert(i == m_nCurrentFrame); |
347 | 0 | UpdateControl(); |
348 | 0 | } |
349 | |
|
350 | 0 | if( pProgress ) |
351 | 0 | { |
352 | 0 | pProgress.reset(); |
353 | 0 | m_xBtnStop->set_sensitive(false); |
354 | 0 | } |
355 | |
|
356 | 0 | m_xRbtGroup->set_sensitive( bRbtGroupEnabled ); |
357 | 0 | m_xBtnGetAllObjects->set_sensitive( bBtnGetAllObjectsEnabled ); |
358 | 0 | m_xBtnGetOneObject->set_sensitive( bBtnGetOneObjectEnabled ); |
359 | 0 | } |
360 | | |
361 | | IMPL_LINK_NOARG(AnimationWindow, ClickLastHdl, weld::Button&, void) |
362 | 0 | { |
363 | 0 | m_nCurrentFrame = |
364 | 0 | (m_FrameList.empty()) ? EMPTY_FRAMELIST : m_FrameList.size() - 1 ; |
365 | 0 | UpdateControl(); |
366 | 0 | } |
367 | | |
368 | | IMPL_LINK_NOARG(AnimationWindow, ClickRbtHdl, weld::Toggleable&, void) |
369 | 0 | { |
370 | 0 | if (m_FrameList.empty() || m_xRbtGroup->get_active()) |
371 | 0 | { |
372 | 0 | m_xTimeField->set_text( OUString() ); |
373 | 0 | m_xTimeField->set_sensitive( false ); |
374 | 0 | m_xLbLoopCount->set_sensitive( false ); |
375 | 0 | } |
376 | 0 | else if (m_xRbtBitmap->get_active()) |
377 | 0 | { |
378 | 0 | sal_uLong n = m_xNumFldBitmap->get_value(); |
379 | 0 | if( n > 0 ) |
380 | 0 | { |
381 | 0 | ::tools::Time const & rTime = m_FrameList[n - 1].second; |
382 | 0 | m_xFormatter->SetTime( rTime ); |
383 | 0 | m_xFormatter->ReFormat(); |
384 | 0 | } |
385 | 0 | m_xTimeField->set_sensitive(true); |
386 | 0 | m_xLbLoopCount->set_sensitive(true); |
387 | 0 | } |
388 | 0 | } |
389 | | |
390 | | IMPL_LINK(AnimationWindow, ClickHelpHdl, weld::Button&, rButton, void) |
391 | 0 | { |
392 | 0 | if (Help* pHelp = Application::GetHelp()) |
393 | 0 | pHelp->Start(m_xContainer->get_help_id(), &rButton); |
394 | 0 | } |
395 | | |
396 | | IMPL_LINK( AnimationWindow, ClickGetObjectHdl, weld::Button&, rBtn, void ) |
397 | 0 | { |
398 | 0 | bAllObjects = &rBtn == m_xBtnGetAllObjects.get(); |
399 | | |
400 | | // Code now in AddObj() |
401 | 0 | SfxBoolItem aItem( SID_ANIMATOR_ADD, true ); |
402 | |
|
403 | 0 | GetBindings().GetDispatcher()->ExecuteList( |
404 | 0 | SID_ANIMATOR_ADD, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); |
405 | 0 | } |
406 | | |
407 | | IMPL_LINK( AnimationWindow, ClickRemoveBitmapHdl, weld::Button&, rBtn, void ) |
408 | 0 | { |
409 | 0 | SdPage* pPage = pMyDoc->GetSdPage(0, PageKind::Standard); |
410 | 0 | rtl::Reference<SdrObject> pObject; |
411 | | |
412 | | // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access |
413 | 0 | if (&rBtn == m_xBtnRemoveBitmap.get() && EMPTY_FRAMELIST != m_nCurrentFrame) |
414 | 0 | { |
415 | 0 | m_FrameList.erase(m_FrameList.begin() + m_nCurrentFrame); |
416 | |
|
417 | 0 | pObject = pPage->GetObj(m_nCurrentFrame); |
418 | | // Through acquisition of the AnimatedGIFs, objects does not need to |
419 | | // exist. |
420 | 0 | if( pObject ) |
421 | 0 | { |
422 | 0 | pObject = pPage->RemoveObject(m_nCurrentFrame); |
423 | 0 | DBG_ASSERT(pObject, "Clone not found during deletion"); |
424 | 0 | pObject.clear(); |
425 | 0 | pPage->RecalcObjOrdNums(); |
426 | 0 | } |
427 | |
|
428 | 0 | if (m_nCurrentFrame >= m_FrameList.size()) |
429 | 0 | { |
430 | | // tdf#95298 last frame was deleted, try to use the one before it or go on empty state |
431 | 0 | m_nCurrentFrame = m_FrameList.empty() ? EMPTY_FRAMELIST : m_FrameList.size() - 1; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | else // delete everything |
435 | 0 | { |
436 | 0 | std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(), |
437 | 0 | VclMessageType::Warning, VclButtonsType::YesNo, |
438 | 0 | SdResId(STR_ASK_DELETE_ALL_PICTURES))); |
439 | 0 | short nReturn = xWarn->run(); |
440 | |
|
441 | 0 | if( nReturn == RET_YES ) |
442 | 0 | { |
443 | | // clear frame list |
444 | 0 | for (size_t i = m_FrameList.size(); i > 0; ) |
445 | 0 | { |
446 | 0 | --i; |
447 | 0 | pObject = pPage->GetObj( i ); |
448 | 0 | if( pObject ) |
449 | 0 | { |
450 | 0 | pObject = pPage->RemoveObject( i ); |
451 | 0 | DBG_ASSERT(pObject, "Clone not found during deletion"); |
452 | 0 | pObject.clear(); |
453 | | //pPage->RecalcObjOrdNums(); |
454 | 0 | } |
455 | 0 | } |
456 | 0 | m_FrameList.clear(); |
457 | 0 | m_nCurrentFrame = EMPTY_FRAMELIST; |
458 | 0 | } |
459 | 0 | } |
460 | | |
461 | | // can we create an animation group |
462 | 0 | if (m_FrameList.empty()) |
463 | 0 | { |
464 | 0 | m_xBtnCreateGroup->set_sensitive(false); |
465 | | // if previous disabled by acquisition of AnimatedGIFs: |
466 | | //m_xRbtBitmap->set_sensitive(true); |
467 | 0 | m_xRbtGroup->set_sensitive(true); |
468 | 0 | } |
469 | | |
470 | | // calculate and set zoom for DisplayWin |
471 | 0 | Fraction aFrac(GetScale()); |
472 | 0 | m_xCtlDisplay->SetScale(aFrac); |
473 | |
|
474 | 0 | UpdateControl(); |
475 | 0 | } |
476 | | |
477 | | IMPL_LINK_NOARG(AnimationWindow, ClickCreateGroupHdl, weld::Button&, void) |
478 | 0 | { |
479 | | // Code now in CreatePresObj() |
480 | 0 | SfxBoolItem aItem( SID_ANIMATOR_CREATE, true ); |
481 | |
|
482 | 0 | GetBindings().GetDispatcher()->ExecuteList(SID_ANIMATOR_CREATE, |
483 | 0 | SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); |
484 | 0 | } |
485 | | |
486 | | IMPL_LINK_NOARG(AnimationWindow, ModifyBitmapHdl, weld::SpinButton&, void) |
487 | 0 | { |
488 | 0 | sal_uLong nBmp = m_xNumFldBitmap->get_value(); |
489 | |
|
490 | 0 | if (nBmp > m_FrameList.size()) |
491 | 0 | { |
492 | 0 | nBmp = m_FrameList.size(); |
493 | 0 | } |
494 | |
|
495 | 0 | m_nCurrentFrame = nBmp - 1; |
496 | |
|
497 | 0 | UpdateControl(); |
498 | 0 | } |
499 | | |
500 | | IMPL_LINK_NOARG(AnimationWindow, ModifyTimeHdl, weld::FormattedSpinButton&, void) |
501 | 0 | { |
502 | 0 | sal_uLong nPos = m_xNumFldBitmap->get_value() - 1; |
503 | |
|
504 | 0 | ::tools::Time & rTime = m_FrameList[nPos].second; |
505 | |
|
506 | 0 | rTime = m_xFormatter->GetTime(); |
507 | 0 | } |
508 | | |
509 | | void AnimationWindow::UpdateControl(bool const bDisableCtrls) |
510 | 0 | { |
511 | | // tdf#95298 check m_nCurrentFrame for EMPTY_FRAMELIST to avoid out-of-bound array access |
512 | 0 | if (!m_FrameList.empty() && EMPTY_FRAMELIST != m_nCurrentFrame) |
513 | 0 | { |
514 | 0 | Bitmap aBmp(m_FrameList[m_nCurrentFrame].first); |
515 | |
|
516 | 0 | SdPage* pPage = pMyDoc->GetSdPage(0, PageKind::Standard); |
517 | 0 | SdrObject *const pObject = pPage->GetObj(m_nCurrentFrame); |
518 | 0 | if( pObject ) |
519 | 0 | { |
520 | 0 | ScopedVclPtrInstance< VirtualDevice > pVD; |
521 | 0 | ::tools::Rectangle aObjRect( pObject->GetCurrentBoundRect() ); |
522 | 0 | Size aObjSize( aObjRect.GetSize() ); |
523 | 0 | Point aOrigin( -aObjRect.Left(), -aObjRect.Top() ); |
524 | 0 | MapMode aMap( pVD->GetMapMode() ); |
525 | 0 | aMap.SetMapUnit( MapUnit::Map100thMM ); |
526 | 0 | aMap.SetOrigin( aOrigin ); |
527 | 0 | pVD->SetMapMode( aMap ); |
528 | 0 | pVD->SetOutputSize( aObjSize ); |
529 | 0 | const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings(); |
530 | 0 | pVD->SetBackground( Wallpaper( rStyles.GetFieldColor() ) ); |
531 | 0 | pVD->SetDrawMode( rStyles.GetHighContrastMode() |
532 | 0 | ? sd::OUTPUT_DRAWMODE_CONTRAST |
533 | 0 | : sd::OUTPUT_DRAWMODE_COLOR ); |
534 | 0 | pVD->Erase(); |
535 | 0 | pObject->SingleObjectPainter( *pVD ); |
536 | 0 | aBmp = pVD->GetBitmap( aObjRect.TopLeft(), aObjSize ); |
537 | 0 | } |
538 | |
|
539 | 0 | m_xCtlDisplay->SetBitmap(&aBmp); |
540 | 0 | } |
541 | 0 | else |
542 | 0 | { |
543 | 0 | m_xCtlDisplay->SetBitmap(nullptr); |
544 | 0 | } |
545 | |
|
546 | 0 | m_xCtlDisplay->Invalidate(); |
547 | |
|
548 | 0 | m_xFiCount->set_label(OUString::number( |
549 | 0 | m_FrameList.size())); |
550 | |
|
551 | 0 | if (!m_FrameList.empty() && !bMovie) |
552 | 0 | { |
553 | 0 | assert(m_nCurrentFrame != EMPTY_FRAMELIST && "only arises when m_FrameList.empty()"); |
554 | |
|
555 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
556 | 0 | m_xNumFldBitmap->set_value(nIndex); |
557 | | |
558 | | // if there is at least 1 object in the list |
559 | 0 | m_xBtnFirst->set_sensitive(true); |
560 | 0 | m_xBtnReverse->set_sensitive(true); |
561 | 0 | m_xBtnPlay->set_sensitive(true); |
562 | 0 | m_xBtnLast->set_sensitive(true); |
563 | 0 | m_xNumFldBitmap->set_sensitive(true); |
564 | 0 | m_xTimeField->set_sensitive(true); |
565 | 0 | m_xLbLoopCount->set_sensitive(true); |
566 | 0 | m_xBtnRemoveBitmap->set_sensitive(true); |
567 | 0 | m_xBtnRemoveAll->set_sensitive(true); |
568 | 0 | } |
569 | 0 | else |
570 | 0 | { |
571 | | // if no object is in the list |
572 | 0 | m_xBtnFirst->set_sensitive( false ); |
573 | 0 | m_xBtnReverse->set_sensitive( false ); |
574 | 0 | m_xBtnPlay->set_sensitive( false ); |
575 | 0 | m_xBtnLast->set_sensitive( false ); |
576 | 0 | m_xNumFldBitmap->set_sensitive( false ); |
577 | 0 | m_xTimeField->set_sensitive( false ); |
578 | 0 | m_xLbLoopCount->set_sensitive( false ); |
579 | 0 | m_xBtnRemoveBitmap->set_sensitive( false ); |
580 | 0 | m_xBtnRemoveAll->set_sensitive( false ); |
581 | 0 | } |
582 | |
|
583 | 0 | if( bMovie && bDisableCtrls ) |
584 | 0 | { |
585 | 0 | m_xBtnGetOneObject->set_sensitive( false ); |
586 | 0 | m_xBtnGetAllObjects->set_sensitive( false ); |
587 | 0 | m_xRbtGroup->set_sensitive( false ); |
588 | 0 | m_xRbtBitmap->set_sensitive( false ); |
589 | 0 | m_xBtnCreateGroup->set_sensitive( false ); |
590 | 0 | m_xFtAdjustment->set_sensitive( false ); |
591 | 0 | m_xLbAdjustment->set_sensitive( false ); |
592 | 0 | } |
593 | 0 | else |
594 | 0 | { |
595 | | // enable 'group object' only if it is not an Animated GIF |
596 | 0 | if (m_FrameList.empty()) |
597 | 0 | { |
598 | 0 | m_xRbtGroup->set_sensitive(true); |
599 | 0 | } |
600 | |
|
601 | 0 | m_xRbtBitmap->set_sensitive(true); |
602 | 0 | m_xBtnCreateGroup->set_sensitive(!m_FrameList.empty()); |
603 | 0 | m_xFtAdjustment->set_sensitive(true); |
604 | 0 | m_xLbAdjustment->set_sensitive(true); |
605 | 0 | } |
606 | |
|
607 | 0 | ClickRbtHdl(*m_xRbtGroup); |
608 | 0 | } |
609 | | |
610 | | void AnimationWindow::ResetAttrs() |
611 | 0 | { |
612 | 0 | m_xRbtGroup->set_active(true); |
613 | 0 | m_xLbAdjustment->set_active( BA_CENTER ); |
614 | | // LoopCount |
615 | 0 | m_xLbLoopCount->set_active( m_xLbLoopCount->get_count() - 1); |
616 | |
|
617 | 0 | UpdateControl(); |
618 | 0 | } |
619 | | |
620 | | void AnimationWindow::WaitInEffect( sal_uLong nMilliSeconds, sal_uLong nTime, |
621 | | SfxProgress* pProgress ) const |
622 | 0 | { |
623 | 0 | sal_uInt64 aEnd = ::tools::Time::GetSystemTicks() + nMilliSeconds; |
624 | 0 | sal_uInt64 aCurrent = ::tools::Time::GetSystemTicks(); |
625 | 0 | while (aCurrent < aEnd) |
626 | 0 | { |
627 | 0 | aCurrent = ::tools::Time::GetSystemTicks(); |
628 | |
|
629 | 0 | if( pProgress ) |
630 | 0 | pProgress->SetState( nTime + nMilliSeconds + aCurrent - aEnd ); |
631 | |
|
632 | 0 | Application::Reschedule(); |
633 | |
|
634 | 0 | if( !bMovie ) |
635 | 0 | return; |
636 | 0 | } |
637 | 0 | } |
638 | | |
639 | | Fraction AnimationWindow::GetScale() |
640 | 0 | { |
641 | 0 | Fraction aFrac; |
642 | 0 | size_t const nCount = m_FrameList.size(); |
643 | 0 | if (nCount > 0) |
644 | 0 | { |
645 | 0 | Size aBmpSize(0, 0); |
646 | 0 | for (size_t i = 0; i < nCount; i++) |
647 | 0 | { |
648 | 0 | Bitmap const & rBitmap = m_FrameList[i].first; |
649 | 0 | Size aTempSize( rBitmap.GetSizePixel() ); |
650 | 0 | aBmpSize.setWidth( std::max( aBmpSize.Width(), aTempSize.Width() ) ); |
651 | 0 | aBmpSize.setHeight( std::max( aBmpSize.Height(), aTempSize.Height() ) ); |
652 | 0 | } |
653 | |
|
654 | 0 | aBmpSize.AdjustWidth(10 ); |
655 | 0 | aBmpSize.AdjustHeight(10 ); |
656 | |
|
657 | 0 | Size aDisplaySize(m_xCtlDisplay->GetOutputSizePixel()); |
658 | |
|
659 | 0 | aFrac = Fraction( std::min( static_cast<double>(aDisplaySize.Width()) / static_cast<double>(aBmpSize.Width()), |
660 | 0 | static_cast<double>(aDisplaySize.Height()) / static_cast<double>(aBmpSize.Height()) ) ); |
661 | 0 | } |
662 | 0 | return aFrac; |
663 | 0 | } |
664 | | |
665 | | void AnimationWindow::Resize() |
666 | 0 | { |
667 | 0 | SfxDockingWindow::Resize(); |
668 | 0 | Fraction aFrac(GetScale()); |
669 | 0 | m_xCtlDisplay->SetScale(aFrac); |
670 | 0 | } |
671 | | |
672 | | bool AnimationWindow::Close() |
673 | 0 | { |
674 | 0 | if( maPlayLock.isLocked() ) |
675 | 0 | { |
676 | 0 | return false; |
677 | 0 | } |
678 | 0 | else |
679 | 0 | { |
680 | 0 | SfxBoolItem aItem( SID_ANIMATION_OBJECTS, false ); |
681 | |
|
682 | 0 | GetBindings().GetDispatcher()->ExecuteList( |
683 | 0 | SID_ANIMATION_OBJECTS, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, |
684 | 0 | { &aItem }); |
685 | |
|
686 | 0 | SfxDockingWindow::Close(); |
687 | |
|
688 | 0 | return true; |
689 | 0 | } |
690 | 0 | } |
691 | | |
692 | | void AnimationWindow::AddObj (::sd::View& rView ) |
693 | 0 | { |
694 | | // finish text entry mode to ensure that bitmap is identical with object |
695 | 0 | if( rView.IsTextEdit() ) |
696 | 0 | rView.SdrEndTextEdit(); |
697 | | |
698 | | // clone object(s) and insert the clone(s) into the list |
699 | 0 | const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); |
700 | 0 | const size_t nMarkCount = rMarkList.GetMarkCount(); |
701 | 0 | SdPage* pPage = pMyDoc->GetSdPage(0, PageKind::Standard); |
702 | 0 | const size_t nCloneCount = pPage->GetObjCount(); |
703 | |
|
704 | 0 | if (nMarkCount <= 0) |
705 | 0 | return; |
706 | | |
707 | | // If it is ONE animation object or one group object, which was |
708 | | // 'individually taken', we insert the objects separately |
709 | 0 | bool bAnimObj = false; |
710 | 0 | if( nMarkCount == 1 ) |
711 | 0 | { |
712 | 0 | SdrMark* pMark = rMarkList.GetMark(0); |
713 | 0 | SdrObject* pObject = pMark->GetMarkedSdrObj(); |
714 | 0 | SdAnimationInfo* pAnimInfo = SdDrawDocument::GetAnimationInfo( pObject ); |
715 | 0 | SdrInventor nInv = pObject->GetObjInventor(); |
716 | 0 | SdrObjKind nId = pObject->GetObjIdentifier(); |
717 | | |
718 | | // Animated Bitmap (GIF) |
719 | 0 | if( nInv == SdrInventor::Default && nId == SdrObjKind::Graphic && static_cast<SdrGrafObj*>( pObject )->IsAnimated() ) |
720 | 0 | { |
721 | 0 | const SdrGrafObj* pGrafObj = static_cast<SdrGrafObj*>(pObject); |
722 | 0 | Graphic aGraphic( pGrafObj->GetTransformedGraphic() ); |
723 | 0 | sal_uInt16 nCount = 0; |
724 | |
|
725 | 0 | if( aGraphic.IsAnimated() ) |
726 | 0 | nCount = aGraphic.GetAnimation().Count(); |
727 | |
|
728 | 0 | if( nCount > 0 ) |
729 | 0 | { |
730 | 0 | const Animation aAnimation( aGraphic.GetAnimation() ); |
731 | |
|
732 | 0 | for( sal_uInt16 i = 0; i < nCount; i++ ) |
733 | 0 | { |
734 | 0 | const AnimationFrame& rAnimationFrame = aAnimation.Get( i ); |
735 | | |
736 | | // LoopCount |
737 | 0 | if( i == 0 ) |
738 | 0 | { |
739 | 0 | sal_uInt32 nLoopCount = aAnimation.GetLoopCount(); |
740 | |
|
741 | 0 | if( !nLoopCount ) // endless |
742 | 0 | m_xLbLoopCount->set_active( m_xLbLoopCount->get_count() - 1); |
743 | 0 | else |
744 | 0 | m_xLbLoopCount->set_active_text(OUString::number( nLoopCount ) ); |
745 | 0 | } |
746 | |
|
747 | 0 | ::tools::Long nTime = rAnimationFrame.mnWait; |
748 | 0 | ::tools::Time aTime( 0, 0, nTime / 100, nTime % 100 ); |
749 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
750 | 0 | m_FrameList.insert( |
751 | 0 | m_FrameList.begin() + nIndex, |
752 | 0 | ::std::make_pair(rAnimationFrame.maBitmap, aTime)); |
753 | | |
754 | | // increment => next one inserted after this one |
755 | 0 | ++m_nCurrentFrame; |
756 | 0 | } |
757 | | // if an animated GIF is taken, only such one can be created |
758 | 0 | m_xRbtBitmap->set_active(true); |
759 | 0 | m_xRbtGroup->set_sensitive( false ); |
760 | 0 | bAnimObj = true; |
761 | 0 | } |
762 | 0 | } |
763 | 0 | else if( bAllObjects || ( pAnimInfo && pAnimInfo->mbIsMovie ) ) |
764 | 0 | { |
765 | | // several objects |
766 | 0 | SdrObjList* pObjList = static_cast<SdrObjGroup*>(pObject)->GetSubList(); |
767 | |
|
768 | 0 | for (const rtl::Reference<SdrObject>& pSnapShot : *pObjList) |
769 | 0 | { |
770 | 0 | Bitmap aBitmap(SdrExchangeView::GetObjGraphic(*pSnapShot).GetBitmap()); |
771 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
772 | 0 | m_FrameList.insert( |
773 | 0 | m_FrameList.begin() + nIndex, |
774 | 0 | ::std::make_pair(aBitmap, m_xFormatter->GetTime())); |
775 | | |
776 | | // increment => next one inserted after this one |
777 | 0 | ++m_nCurrentFrame; |
778 | | |
779 | | // Clone |
780 | 0 | pPage->InsertObject( |
781 | 0 | pSnapShot->CloneSdrObject(pPage->getSdrModelFromSdrPage()).get(), |
782 | 0 | m_nCurrentFrame); |
783 | 0 | } |
784 | 0 | bAnimObj = true; |
785 | 0 | } |
786 | 0 | } |
787 | | // also one single animated object |
788 | 0 | if( !bAnimObj && !( bAllObjects && nMarkCount > 1 ) ) |
789 | 0 | { |
790 | 0 | Bitmap aBitmap(rView.GetAllMarkedGraphic().GetBitmap()); |
791 | |
|
792 | 0 | ::tools::Time aTime( m_xFormatter->GetTime() ); |
793 | |
|
794 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
795 | 0 | m_FrameList.insert( |
796 | 0 | m_FrameList.begin() + nIndex, |
797 | 0 | ::std::make_pair(aBitmap, aTime)); |
798 | 0 | } |
799 | | |
800 | | // one single object |
801 | 0 | if( nMarkCount == 1 && !bAnimObj ) |
802 | 0 | { |
803 | 0 | SdrMark* pMark = rMarkList.GetMark(0); |
804 | 0 | SdrObject* pObject = pMark->GetMarkedSdrObj(); |
805 | 0 | rtl::Reference<SdrObject> pClone(pObject->CloneSdrObject(pPage->getSdrModelFromSdrPage())); |
806 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
807 | 0 | pPage->InsertObject(pClone.get(), nIndex); |
808 | 0 | } |
809 | | // several objects: group the clones |
810 | 0 | else if (nMarkCount > 1) |
811 | 0 | { |
812 | | // take objects separately |
813 | 0 | if( bAllObjects ) |
814 | 0 | { |
815 | 0 | for( size_t nObject= 0; nObject < nMarkCount; ++nObject ) |
816 | 0 | { |
817 | | // Clone |
818 | 0 | SdrObject* pObject(rMarkList.GetMark(nObject)->GetMarkedSdrObj()); |
819 | 0 | Bitmap aBitmap(SdrExchangeView::GetObjGraphic(*pObject).GetBitmap()); |
820 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
821 | 0 | m_FrameList.insert( |
822 | 0 | m_FrameList.begin() + nIndex, |
823 | 0 | ::std::make_pair(aBitmap, m_xFormatter->GetTime())); |
824 | | |
825 | | // increment => next one inserted after this one |
826 | 0 | ++m_nCurrentFrame; |
827 | |
|
828 | 0 | pPage->InsertObject( |
829 | 0 | pObject->CloneSdrObject(pPage->getSdrModelFromSdrPage()).get(), |
830 | 0 | m_nCurrentFrame); |
831 | 0 | } |
832 | 0 | bAnimObj = true; // that we don't change again |
833 | 0 | } |
834 | 0 | else |
835 | 0 | { |
836 | 0 | rtl::Reference<SdrObjGroup> pCloneGroup = new SdrObjGroup(rView.getSdrModelFromSdrView()); |
837 | 0 | SdrObjList* pObjList = pCloneGroup->GetSubList(); |
838 | |
|
839 | 0 | for (size_t nObject= 0; nObject < nMarkCount; ++nObject) |
840 | 0 | { |
841 | 0 | pObjList->InsertObject( |
842 | 0 | rMarkList.GetMark(nObject)->GetMarkedSdrObj()->CloneSdrObject( |
843 | 0 | pPage->getSdrModelFromSdrPage()).get()); |
844 | 0 | } |
845 | |
|
846 | 0 | size_t nIndex = m_nCurrentFrame + 1; |
847 | 0 | pPage->InsertObject(pCloneGroup.get(), nIndex); |
848 | 0 | } |
849 | 0 | } |
850 | |
|
851 | 0 | if( !bAnimObj ) |
852 | 0 | { |
853 | 0 | ++m_nCurrentFrame; |
854 | 0 | } |
855 | | |
856 | | // if there was nothing in the animator before but now is something |
857 | | // there, we can create an animation group |
858 | 0 | if (nCloneCount == 0 && !m_FrameList.empty()) |
859 | 0 | { |
860 | 0 | m_xBtnCreateGroup->set_sensitive(true); |
861 | 0 | } |
862 | | |
863 | | // calculate and set zoom for DisplayWin |
864 | 0 | Fraction aFrac( GetScale() ); |
865 | 0 | m_xCtlDisplay->SetScale(aFrac); |
866 | |
|
867 | 0 | UpdateControl(); |
868 | 0 | } |
869 | | |
870 | | void AnimationWindow::CreateAnimObj (::sd::View& rView ) |
871 | 0 | { |
872 | 0 | vcl::Window* pOutWin = rView.GetFirstOutputDevice()->GetOwnerWindow(); // GetWin( 0 ); |
873 | 0 | DBG_ASSERT( pOutWin, "Window does not exist!" ); |
874 | | |
875 | | // find window center |
876 | 0 | const MapMode aMap100( MapUnit::Map100thMM ); |
877 | 0 | Size aMaxSizeLog; |
878 | 0 | Size aMaxSizePix; |
879 | 0 | Size aTemp( pOutWin->GetOutputSizePixel() ); |
880 | 0 | const Point aWindowCenter( pOutWin->PixelToLogic( Point( aTemp.Width() >> 1, aTemp.Height() >> 1 ) ) ); |
881 | 0 | const OutputDevice* pDefDev = Application::GetDefaultDevice(); |
882 | 0 | const size_t nCount = m_FrameList.size(); |
883 | 0 | BitmapAdjustment eBA = static_cast<BitmapAdjustment>(m_xLbAdjustment->get_active()); |
884 | | |
885 | | // find biggest bitmap |
886 | 0 | for (size_t i = 0; i < nCount; ++i) |
887 | 0 | { |
888 | 0 | const Bitmap& rBmp = m_FrameList[i].first; |
889 | 0 | const Graphic aGraphic( rBmp ); |
890 | 0 | Size aTmpSizeLog; |
891 | 0 | const Size aTmpSizePix( rBmp.GetSizePixel() ); |
892 | |
|
893 | 0 | if ( aGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel ) |
894 | 0 | aTmpSizeLog = pDefDev->PixelToLogic( aGraphic.GetPrefSize(), aMap100 ); |
895 | 0 | else |
896 | 0 | aTmpSizeLog = OutputDevice::LogicToLogic( aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), aMap100 ); |
897 | |
|
898 | 0 | aMaxSizeLog.setWidth( std::max( aMaxSizeLog.Width(), aTmpSizeLog.Width() ) ); |
899 | 0 | aMaxSizeLog.setHeight( std::max( aMaxSizeLog.Height(), aTmpSizeLog.Height() ) ); |
900 | |
|
901 | 0 | aMaxSizePix.setWidth( std::max( aMaxSizePix.Width(), aTmpSizePix.Width() ) ); |
902 | 0 | aMaxSizePix.setHeight( std::max( aMaxSizePix.Height(), aTmpSizePix.Height() ) ); |
903 | 0 | } |
904 | |
|
905 | 0 | SdrPageView* pPV = rView.GetSdrPageView(); |
906 | |
|
907 | 0 | if( m_xRbtBitmap->get_active() ) |
908 | 0 | { |
909 | | // create bitmap group (Animated GIF) |
910 | 0 | Animation aAnimation; |
911 | 0 | Point aPt; |
912 | |
|
913 | 0 | for (size_t i = 0; i < nCount; ++i) |
914 | 0 | { |
915 | 0 | ::tools::Time const & rTime = m_FrameList[i].second; |
916 | 0 | ::tools::Long nTime = rTime.GetNanoSec(); |
917 | 0 | nTime += rTime.GetSec() * 100; |
918 | |
|
919 | 0 | Bitmap const & rBitmap = m_FrameList[i].first; |
920 | | |
921 | | // calculate offset for the specified direction |
922 | 0 | const Size aBitmapSize( rBitmap.GetSizePixel() ); |
923 | |
|
924 | 0 | switch( eBA ) |
925 | 0 | { |
926 | 0 | case BA_LEFT_UP: |
927 | 0 | break; |
928 | | |
929 | 0 | case BA_LEFT: |
930 | 0 | aPt.setY( (aMaxSizePix.Height() - aBitmapSize.Height()) >> 1 ); |
931 | 0 | break; |
932 | | |
933 | 0 | case BA_LEFT_DOWN: |
934 | 0 | aPt.setY( aMaxSizePix.Height() - aBitmapSize.Height() ); |
935 | 0 | break; |
936 | | |
937 | 0 | case BA_UP: |
938 | 0 | aPt.setX( (aMaxSizePix.Width() - aBitmapSize.Width()) >> 1 ); |
939 | 0 | break; |
940 | | |
941 | 0 | case BA_CENTER: |
942 | 0 | aPt.setX( (aMaxSizePix.Width() - aBitmapSize.Width()) >> 1 ); |
943 | 0 | aPt.setY( (aMaxSizePix.Height() - aBitmapSize.Height()) >> 1 ); |
944 | 0 | break; |
945 | | |
946 | 0 | case BA_DOWN: |
947 | 0 | aPt.setX( (aMaxSizePix.Width() - aBitmapSize.Width()) >> 1 ); |
948 | 0 | aPt.setY( aMaxSizePix.Height() - aBitmapSize.Height() ); |
949 | 0 | break; |
950 | | |
951 | 0 | case BA_RIGHT_UP: |
952 | 0 | aPt.setX( aMaxSizePix.Width() - aBitmapSize.Width() ); |
953 | 0 | break; |
954 | | |
955 | 0 | case BA_RIGHT: |
956 | 0 | aPt.setX( aMaxSizePix.Width() - aBitmapSize.Width() ); |
957 | 0 | aPt.setY( (aMaxSizePix.Height() - aBitmapSize.Height()) >> 1 ); |
958 | 0 | break; |
959 | | |
960 | 0 | case BA_RIGHT_DOWN: |
961 | 0 | aPt.setX( aMaxSizePix.Width() - aBitmapSize.Width() ); |
962 | 0 | aPt.setY( aMaxSizePix.Height() - aBitmapSize.Height() ); |
963 | 0 | break; |
964 | |
|
965 | 0 | } |
966 | | |
967 | | // find LoopCount (number of passes) |
968 | 0 | AnimationFrame aAnimationFrame; |
969 | 0 | sal_uInt32 nLoopCount = 0; |
970 | 0 | sal_Int32 nPos = m_xLbLoopCount->get_active(); |
971 | |
|
972 | 0 | if( nPos != -1 && nPos != m_xLbLoopCount->get_count() - 1 ) // endless |
973 | 0 | nLoopCount = m_xLbLoopCount->get_active_text().toUInt32(); |
974 | |
|
975 | 0 | aAnimationFrame.maBitmap = rBitmap; |
976 | 0 | aAnimationFrame.maPositionPixel = aPt; |
977 | 0 | aAnimationFrame.maSizePixel = aBitmapSize; |
978 | 0 | aAnimationFrame.mnWait = nTime; |
979 | 0 | aAnimationFrame.meDisposal = Disposal::Back; |
980 | 0 | aAnimationFrame.mbUserInput = false; |
981 | |
|
982 | 0 | aAnimation.Insert( aAnimationFrame ); |
983 | 0 | aAnimation.SetDisplaySizePixel( aMaxSizePix ); |
984 | 0 | aAnimation.SetLoopCount( nLoopCount ); |
985 | 0 | } |
986 | | |
987 | 0 | rtl::Reference<SdrGrafObj> pGrafObj = new SdrGrafObj( |
988 | 0 | rView.getSdrModelFromSdrView(), |
989 | 0 | Graphic(aAnimation)); |
990 | 0 | const Point aOrg( aWindowCenter.X() - ( aMaxSizeLog.Width() >> 1 ), aWindowCenter.Y() - ( aMaxSizeLog.Height() >> 1 ) ); |
991 | |
|
992 | 0 | pGrafObj->SetLogicRect( ::tools::Rectangle( aOrg, aMaxSizeLog ) ); |
993 | 0 | rView.InsertObjectAtView( pGrafObj.get(), *pPV, SdrInsertFlags::SETDEFLAYER); |
994 | 0 | } |
995 | 0 | else |
996 | 0 | { |
997 | | // calculate offset for the specified direction |
998 | 0 | Size aOffset; |
999 | 0 | SdrObject * pClone = nullptr; |
1000 | 0 | SdPage* pPage = pMyDoc->GetSdPage(0, PageKind::Standard); |
1001 | |
|
1002 | 0 | for (size_t i = 0; i < nCount; ++i) |
1003 | 0 | { |
1004 | 0 | pClone = pPage->GetObj(i); |
1005 | 0 | ::tools::Rectangle aRect( pClone->GetSnapRect() ); |
1006 | |
|
1007 | 0 | switch( eBA ) |
1008 | 0 | { |
1009 | 0 | case BA_LEFT_UP: |
1010 | 0 | break; |
1011 | | |
1012 | 0 | case BA_LEFT: |
1013 | 0 | aOffset.setHeight( (aMaxSizeLog.Height() - aRect.GetHeight()) / 2 ); |
1014 | 0 | break; |
1015 | | |
1016 | 0 | case BA_LEFT_DOWN: |
1017 | 0 | aOffset.setHeight( aMaxSizeLog.Height() - aRect.GetHeight() ); |
1018 | 0 | break; |
1019 | | |
1020 | 0 | case BA_UP: |
1021 | 0 | aOffset.setWidth( (aMaxSizeLog.Width() - aRect.GetWidth()) / 2 ); |
1022 | 0 | break; |
1023 | | |
1024 | 0 | case BA_CENTER: |
1025 | 0 | aOffset.setWidth( (aMaxSizeLog.Width() - aRect.GetWidth()) / 2 ); |
1026 | 0 | aOffset.setHeight( (aMaxSizeLog.Height() - aRect.GetHeight()) / 2 ); |
1027 | 0 | break; |
1028 | | |
1029 | 0 | case BA_DOWN: |
1030 | 0 | aOffset.setWidth( (aMaxSizeLog.Width() - aRect.GetWidth()) / 2 ); |
1031 | 0 | aOffset.setHeight( aMaxSizeLog.Height() - aRect.GetHeight() ); |
1032 | 0 | break; |
1033 | | |
1034 | 0 | case BA_RIGHT_UP: |
1035 | 0 | aOffset.setWidth( aMaxSizeLog.Width() - aRect.GetWidth() ); |
1036 | 0 | break; |
1037 | | |
1038 | 0 | case BA_RIGHT: |
1039 | 0 | aOffset.setWidth( aMaxSizeLog.Width() - aRect.GetWidth() ); |
1040 | 0 | aOffset.setHeight( (aMaxSizeLog.Height() - aRect.GetHeight()) / 2 ); |
1041 | 0 | break; |
1042 | | |
1043 | 0 | case BA_RIGHT_DOWN: |
1044 | 0 | aOffset.setWidth( aMaxSizeLog.Width() - aRect.GetWidth() ); |
1045 | 0 | aOffset.setHeight( aMaxSizeLog.Height() - aRect.GetHeight() ); |
1046 | 0 | break; |
1047 | |
|
1048 | 0 | } |
1049 | | // Unfortunately, SetSnapRect is not implemented for ellipses !!! |
1050 | 0 | Point aMovePt( aWindowCenter + Point( aOffset.Width(), aOffset.Height() ) - aRect.TopLeft() ); |
1051 | 0 | Size aMoveSize( aMovePt.X(), aMovePt.Y() ); |
1052 | 0 | pClone->NbcMove( aMoveSize ); |
1053 | 0 | } |
1054 | | |
1055 | | // #i42894# Caution(!) variable pPage looks right, but it is a page from the local |
1056 | | // document the dialog is using (!), so get the target page from the target view |
1057 | 0 | SdPage* pTargetSdPage = dynamic_cast< SdPage* >(rView.GetSdrPageView() ? rView.GetSdrPageView()->GetPage() : nullptr); |
1058 | |
|
1059 | 0 | if(pTargetSdPage) |
1060 | 0 | { |
1061 | | // create animation group |
1062 | 0 | rtl::Reference<SdrObjGroup> pGroup = new SdrObjGroup(rView.getSdrModelFromSdrView()); |
1063 | 0 | SdrObjList* pObjList = pGroup->GetSubList(); |
1064 | |
|
1065 | 0 | for (size_t i = 0; i < nCount; ++i) |
1066 | 0 | { |
1067 | | // the clone remains in the animation; we insert a clone of the |
1068 | | // clone into the group |
1069 | 0 | pClone = pPage->GetObj(i); |
1070 | 0 | rtl::Reference<SdrObject> pCloneOfClone(pClone->CloneSdrObject(pTargetSdPage->getSdrModelFromSdrPage())); |
1071 | | //SdrObject* pCloneOfClone = pPage->GetObj(i)->Clone(); |
1072 | 0 | pObjList->InsertObject(pCloneOfClone.get()); |
1073 | 0 | } |
1074 | | |
1075 | | // until now the top left corner of the group is in the window center; |
1076 | | // correct the position by half of the size of the group |
1077 | 0 | aTemp = aMaxSizeLog; |
1078 | 0 | aTemp.setHeight( - aTemp.Height() / 2 ); |
1079 | 0 | aTemp.setWidth( - aTemp.Width() / 2 ); |
1080 | 0 | pGroup->NbcMove(aTemp); |
1081 | | |
1082 | | // #i42894# create needed SMIL stuff and move child objects to page directly (see |
1083 | | // comments at EffectMigration::CreateAnimatedGroup why this has to be done). |
1084 | 0 | EffectMigration::CreateAnimatedGroup(*pGroup, *pTargetSdPage); |
1085 | 0 | } |
1086 | 0 | } |
1087 | | |
1088 | 0 | ClickFirstHdl(*m_xBtnFirst); |
1089 | 0 | } |
1090 | | |
1091 | | void AnimationWindow::DataChanged( const DataChangedEvent& rDCEvt ) |
1092 | 0 | { |
1093 | 0 | SfxDockingWindow::DataChanged( rDCEvt ); |
1094 | |
|
1095 | 0 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) |
1096 | 0 | { |
1097 | 0 | UpdateControl(); |
1098 | 0 | } |
1099 | 0 | } |
1100 | | |
1101 | | /** |
1102 | | * ControllerItem for Animator |
1103 | | */ |
1104 | | AnimationControllerItem::AnimationControllerItem( |
1105 | | sal_uInt16 _nId, |
1106 | | AnimationWindow* pAnimWin, |
1107 | | SfxBindings* _pBindings) |
1108 | 0 | : SfxControllerItem( _nId, *_pBindings ), |
1109 | 0 | pAnimationWin( pAnimWin ) |
1110 | 0 | { |
1111 | 0 | } |
1112 | | |
1113 | | void AnimationControllerItem::StateChangedAtToolBoxControl( sal_uInt16 nSId, |
1114 | | SfxItemState eState, const SfxPoolItem* pItem ) |
1115 | 0 | { |
1116 | 0 | if( eState >= SfxItemState::DEFAULT && nSId == SID_ANIMATOR_STATE ) |
1117 | 0 | { |
1118 | 0 | const SfxUInt16Item* pStateItem = dynamic_cast< const SfxUInt16Item*>( pItem ); |
1119 | 0 | assert(pStateItem); //SfxUInt16Item expected |
1120 | 0 | if (pStateItem) |
1121 | 0 | { |
1122 | 0 | sal_uInt16 nState = pStateItem->GetValue(); |
1123 | 0 | pAnimationWin->m_xBtnGetOneObject->set_sensitive( nState & 1 ); |
1124 | 0 | pAnimationWin->m_xBtnGetAllObjects->set_sensitive( nState & 2 ); |
1125 | 0 | } |
1126 | 0 | } |
1127 | 0 | } |
1128 | | |
1129 | | } // end of namespace sd |
1130 | | |
1131 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |