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 <config_features.h>
21
22 #include <com/sun/star/presentation/EffectNodeType.hpp>
23 #include <com/sun/star/animations/Timing.hpp>
24 #include <com/sun/star/animations/Event.hpp>
25 #include <com/sun/star/animations/EventTrigger.hpp>
26 #include <com/sun/star/animations/AnimationFill.hpp>
27 #include <com/sun/star/presentation/TextAnimationType.hpp>
28 #include <com/sun/star/animations/ValuePair.hpp>
29 #include <com/sun/star/awt/FontSlant.hpp>
30 #include <com/sun/star/awt/FontWeight.hpp>
31 #include <com/sun/star/awt/FontUnderline.hpp>
32 #include <com/sun/star/drawing/XDrawPage.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/media/XPlayer.hpp>
35
36 #include <memory>
37
38 #include <comphelper/lok.hxx>
39 #include <i18nutil/unicode.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/stdtext.hxx>
42 #include <vcl/weld.hxx>
43 #include <vcl/settings.hxx>
44
45 #include <svtools/ctrltool.hxx>
46 #include <sfx2/objsh.hxx>
47 #include <tools/debug.hxx>
48 #include <tools/urlobj.hxx>
49 #include <tools/diagnose_ex.h>
50
51 #include <editeng/flstitem.hxx>
52
53 #include <svx/colorbox.hxx>
54 #include <svx/gallery.hxx>
55
56 #include <editeng/editids.hrc>
57 #include <sdresid.hxx>
58
59 #include "CustomAnimationDialog.hxx"
60 #include <CustomAnimationPane.hxx>
61 #include "STLPropertySet.hxx"
62 #include <CustomAnimationPreset.hxx>
63
64 #include <avmedia/mediawindow.hxx>
65
66 #include <filedlg.hxx>
67 #include <strings.hrc>
68 #include <helpids.h>
69
70 using namespace ::com::sun::star;
71 using namespace ::com::sun::star::animations;
72 using namespace ::com::sun::star::presentation;
73
74 using ::com::sun::star::uno::UNO_QUERY;
75 using ::com::sun::star::uno::Any;
76 using ::com::sun::star::uno::makeAny;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::uno::Reference;
79 using ::com::sun::star::uno::Exception;
80 using ::com::sun::star::drawing::XShape;
81 using ::com::sun::star::drawing::XDrawPage;
82 using ::com::sun::star::beans::XPropertySet;
83
84 namespace sd {
85
SdPropertySubControl(weld::Container * pParent)86 SdPropertySubControl::SdPropertySubControl(weld::Container* pParent)
87 : mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationfragment.ui"))
88 , mxContainer(mxBuilder->weld_container("EffectFragment"))
89 , mpParent(pParent)
90 {
91 }
92
~SdPropertySubControl()93 SdPropertySubControl::~SdPropertySubControl()
94 {
95 mpParent->move(mxContainer.get(), nullptr);
96 }
97
98 namespace {
99
100 class SdPresetPropertyBox : public SdPropertySubControl
101 {
102 public:
103 SdPresetPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const OUString& aPresetId, const Link<LinkParamNone*,void>& rModifyHdl);
104
105 virtual Any getValue() override;
106 virtual void setValue( const Any& rValue, const OUString& rPresetId ) override;
107
108 private:
109 std::vector<OUString> maPropertyValues;
110 Link<LinkParamNone*,void> maModifyLink;
111 std::unique_ptr<weld::ComboBox> mxControl;
112
113 DECL_LINK(OnSelect, weld::ComboBox&, void);
114 };
115
116 }
117
SdPresetPropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const OUString & aPresetId,const Link<LinkParamNone *,void> & rModifyHdl)118 SdPresetPropertyBox::SdPresetPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const OUString& aPresetId, const Link<LinkParamNone*,void>& rModifyHdl)
119 : SdPropertySubControl(pParent)
120 , maModifyLink(rModifyHdl)
121 , mxControl(mxBuilder->weld_combo_box("combo"))
122 {
123 mxControl->connect_changed(LINK(this, SdPresetPropertyBox, OnSelect));
124 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_PRESETPROPERTYBOX);
125 mxControl->show();
126 pLabel->set_mnemonic_widget(mxControl.get());
127 setValue(rValue, aPresetId);
128 }
129
IMPL_LINK_NOARG(SdPresetPropertyBox,OnSelect,weld::ComboBox &,void)130 IMPL_LINK_NOARG(SdPresetPropertyBox, OnSelect, weld::ComboBox&, void)
131 {
132 maModifyLink.Call(nullptr);
133 }
134
setValue(const Any & rValue,const OUString & rPresetId)135 void SdPresetPropertyBox::setValue( const Any& rValue, const OUString& rPresetId )
136 {
137 if (!mxControl)
138 return;
139
140 mxControl->freeze();
141 mxControl->clear();
142 maPropertyValues.clear();
143 int nPos = -1;
144
145 const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
146 CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( rPresetId );
147 if( pDescriptor )
148 {
149
150 OUString aPropertyValue;
151 rValue >>= aPropertyValue;
152
153 std::vector<OUString> aSubTypes( pDescriptor->getSubTypes() );
154
155 mxControl->set_sensitive(!aSubTypes.empty());
156
157 for( const auto& aSubType : aSubTypes )
158 {
159 mxControl->append_text(rPresets.getUINameForProperty(aSubType));
160 maPropertyValues.push_back(aSubType);
161 if (aSubType == aPropertyValue)
162 nPos = maPropertyValues.size() - 1;
163 }
164 }
165 else
166 {
167 mxControl->set_sensitive(false);
168 }
169 mxControl->thaw();
170 if (nPos != -1)
171 mxControl->set_active(nPos);
172 }
173
getValue()174 Any SdPresetPropertyBox::getValue()
175 {
176 const int nIndex = mxControl->get_active();
177 if (nIndex == -1)
178 return Any();
179 return makeAny(maPropertyValues[nIndex]);
180 }
181
182 namespace {
183
184 class SdColorPropertyBox : public SdPropertySubControl
185 {
186 public:
187 SdColorPropertyBox(weld::Label* pLabel, weld::Container* pParent, weld::Window* pTopLevel, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
188
189 virtual Any getValue() override;
190 virtual void setValue( const Any& rValue, const OUString& rPresetId ) override;
191
192 private:
193 Link<LinkParamNone*,void> maModifyLink;
194 std::unique_ptr<ColorListBox> mxControl;
195
196 DECL_LINK(OnSelect, ColorListBox&, void);
197 };
198
199 }
200
SdColorPropertyBox(weld::Label * pLabel,weld::Container * pParent,weld::Window * pTopLevel,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)201 SdColorPropertyBox::SdColorPropertyBox(weld::Label* pLabel, weld::Container* pParent, weld::Window* pTopLevel, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
202 : SdPropertySubControl(pParent)
203 , maModifyLink(rModifyHdl)
204 , mxControl(new ColorListBox(mxBuilder->weld_menu_button("color"), [pTopLevel]{ return pTopLevel; }))
205 {
206 mxControl->SetSelectHdl(LINK(this, SdColorPropertyBox, OnSelect));
207 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_COLORPROPERTYBOX);
208 pLabel->set_mnemonic_widget(&mxControl->get_widget());
209 mxControl->show();
210
211 Color nColor;
212 rValue >>= nColor;
213 mxControl->SelectEntry(nColor);
214 }
215
IMPL_LINK_NOARG(SdColorPropertyBox,OnSelect,ColorListBox &,void)216 IMPL_LINK_NOARG(SdColorPropertyBox, OnSelect, ColorListBox&, void)
217 {
218 maModifyLink.Call(nullptr);
219 }
220
setValue(const Any & rValue,const OUString &)221 void SdColorPropertyBox::setValue( const Any& rValue, const OUString& )
222 {
223 if (mxControl)
224 {
225 Color nColor;
226 rValue >>= nColor;
227
228 mxControl->SetNoSelection();
229 mxControl->SelectEntry(nColor);
230 }
231 }
232
getValue()233 Any SdColorPropertyBox::getValue()
234 {
235 return makeAny(sal_Int32(mxControl->GetSelectEntryColor().GetRGBColor()));
236 }
237
238 namespace {
239
240 class SdFontPropertyBox : public SdPropertySubControl
241 {
242 public:
243 SdFontPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
244
245 virtual Any getValue() override;
246 virtual void setValue(const Any& rValue, const OUString& rPresetId) override;
247
248 private:
249 Link<LinkParamNone*,void> maModifyHdl;
250 std::unique_ptr<weld::ComboBox> mxControl;
251
252 DECL_LINK(ControlSelectHdl, weld::ComboBox&, void);
253 };
254
255 }
256
SdFontPropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)257 SdFontPropertyBox::SdFontPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
258 : SdPropertySubControl(pParent)
259 , maModifyHdl(rModifyHdl)
260 , mxControl(mxBuilder->weld_combo_box("fontname"))
261 {
262 mxControl->connect_changed(LINK(this, SdFontPropertyBox, ControlSelectHdl));
263 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTPROPERTYBOX);
264 mxControl->show();
265 pLabel->set_mnemonic_widget(mxControl.get());
266
267 SfxObjectShell* pDocSh = SfxObjectShell::Current();
268 const FontList* pFontList = nullptr;
269 bool bMustDelete = false;
270
271 if (pDocSh)
272 {
273 auto pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
274 if (pItem)
275 pFontList = static_cast<const SvxFontListItem*>(pItem)->GetFontList();
276 }
277
278 if (!pFontList)
279 {
280 pFontList = new FontList(Application::GetDefaultDevice(), nullptr);
281 bMustDelete = true;
282 }
283
284 mxControl->freeze();
285
286 sal_uInt16 nFontCount = pFontList->GetFontNameCount();
287 for (sal_uInt16 i = 0; i < nFontCount; ++i)
288 {
289 const FontMetric& rFontMetric = pFontList->GetFontName(i);
290 mxControl->append_text(rFontMetric.GetFamilyName());
291 }
292
293 mxControl->thaw();
294
295 if( bMustDelete )
296 delete pFontList;
297
298 setValue( rValue, OUString() );
299 }
300
IMPL_LINK_NOARG(SdFontPropertyBox,ControlSelectHdl,weld::ComboBox &,void)301 IMPL_LINK_NOARG(SdFontPropertyBox, ControlSelectHdl, weld::ComboBox&, void)
302 {
303 maModifyHdl.Call(nullptr);
304 }
305
setValue(const Any & rValue,const OUString &)306 void SdFontPropertyBox::setValue( const Any& rValue, const OUString& )
307 {
308 if (mxControl)
309 {
310 OUString aFontName;
311 rValue >>= aFontName;
312 mxControl->set_entry_text(aFontName);
313 }
314 }
315
getValue()316 Any SdFontPropertyBox::getValue()
317 {
318 OUString aFontName(mxControl->get_active_text());
319 return makeAny(aFontName);
320 }
321
322 namespace {
323
324 class SdCharHeightPropertyBox : public SdPropertySubControl
325 {
326 public:
327 SdCharHeightPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
328
329 virtual Any getValue() override;
330 virtual void setValue( const Any& rValue, const OUString& ) override;
331
332 DECL_LINK(implMenuSelectHdl, const OString& rIdent, void);
333
334 private:
335 Link<LinkParamNone*,void> maModifyHdl;
336 std::unique_ptr<weld::MetricSpinButton> mxMetric;
337 std::unique_ptr<weld::MenuButton> mxControl;
338
339 DECL_LINK(EditModifyHdl, weld::MetricSpinButton&, void);
340 };
341
342 }
343
SdCharHeightPropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)344 SdCharHeightPropertyBox::SdCharHeightPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
345 : SdPropertySubControl(pParent)
346 , maModifyHdl(rModifyHdl)
347 , mxMetric(mxBuilder->weld_metric_spin_button("fontsize", FieldUnit::PERCENT))
348 , mxControl(mxBuilder->weld_menu_button("fontsizemenu"))
349 {
350 mxMetric->connect_value_changed(LINK(this, SdCharHeightPropertyBox, EditModifyHdl));
351 mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_CHARHEIGHTPROPERTYBOX);
352 mxMetric->show();
353 pLabel->set_mnemonic_widget(&mxMetric->get_widget());
354
355 mxControl->connect_selected(LINK(this, SdCharHeightPropertyBox, implMenuSelectHdl));
356 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_CHARHEIGHTPROPERTYBOX);
357 mxControl->show();
358
359 setValue(rValue, OUString());
360 }
361
IMPL_LINK_NOARG(SdCharHeightPropertyBox,EditModifyHdl,weld::MetricSpinButton &,void)362 IMPL_LINK_NOARG(SdCharHeightPropertyBox, EditModifyHdl, weld::MetricSpinButton&, void)
363 {
364 maModifyHdl.Call(nullptr);
365 }
366
IMPL_LINK(SdCharHeightPropertyBox,implMenuSelectHdl,const OString &,rIdent,void)367 IMPL_LINK(SdCharHeightPropertyBox, implMenuSelectHdl, const OString&, rIdent, void)
368 {
369 sal_Int32 nValue = rIdent.toInt32();
370 mxMetric->set_value(nValue, FieldUnit::PERCENT);
371 EditModifyHdl(*mxMetric);
372 }
373
setValue(const Any & rValue,const OUString &)374 void SdCharHeightPropertyBox::setValue( const Any& rValue, const OUString& )
375 {
376 if (mxMetric)
377 {
378 double fValue = 0.0;
379 rValue >>= fValue;
380 mxMetric->set_value(static_cast<::tools::Long>(fValue * 100.0), FieldUnit::PERCENT);
381 }
382 }
383
getValue()384 Any SdCharHeightPropertyBox::getValue()
385 {
386 return makeAny(static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0);
387 }
388
389 namespace {
390
391 class SdTransparencyPropertyBox : public SdPropertySubControl
392 {
393 public:
394 SdTransparencyPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
395
396 virtual Any getValue() override;
397 virtual void setValue( const Any& rValue, const OUString& rPresetId ) override;
398
399 DECL_LINK(implMenuSelectHdl, const OString&, void);
400 DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);
401
402 void updateMenu();
403
404 private:
405 Link<LinkParamNone*,void> maModifyHdl;
406
407 std::unique_ptr<weld::MetricSpinButton> mxMetric;
408 std::unique_ptr<weld::MenuButton> mxControl;
409 };
410
411 }
412
SdTransparencyPropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)413 SdTransparencyPropertyBox::SdTransparencyPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
414 : SdPropertySubControl(pParent)
415 , maModifyHdl(rModifyHdl)
416 , mxMetric(mxBuilder->weld_metric_spin_button("transparent", FieldUnit::PERCENT))
417 , mxControl(mxBuilder->weld_menu_button("transparentmenu"))
418 {
419 for (sal_Int32 i = 25; i < 101; i += 25)
420 {
421 OUString aStr(unicode::formatPercent(i,
422 Application::GetSettings().GetUILanguageTag()));
423 mxControl->append_item_check(OUString::number(i), aStr);
424 }
425
426 mxControl->connect_selected(LINK(this, SdTransparencyPropertyBox, implMenuSelectHdl));
427 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_TRANSPARENCYPROPERTYBOX);
428 mxControl->show();
429
430 mxMetric->connect_value_changed(LINK(this, SdTransparencyPropertyBox, implModifyHdl));
431 mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_TRANSPARENCYPROPERTYBOX);
432 mxMetric->show();
433 pLabel->set_mnemonic_widget(&mxMetric->get_widget());
434
435 setValue(rValue, OUString());
436 }
437
updateMenu()438 void SdTransparencyPropertyBox::updateMenu()
439 {
440 sal_Int64 nValue = mxMetric->get_value(FieldUnit::PERCENT);
441 for (sal_uInt16 i = 25; i < 101; i += 25)
442 mxControl->set_item_active(OString::number(i), nValue == i);
443 }
444
IMPL_LINK_NOARG(SdTransparencyPropertyBox,implModifyHdl,weld::MetricSpinButton &,void)445 IMPL_LINK_NOARG(SdTransparencyPropertyBox, implModifyHdl, weld::MetricSpinButton&, void)
446 {
447 updateMenu();
448 maModifyHdl.Call(nullptr);
449 }
450
IMPL_LINK(SdTransparencyPropertyBox,implMenuSelectHdl,const OString &,rIdent,void)451 IMPL_LINK(SdTransparencyPropertyBox, implMenuSelectHdl, const OString&, rIdent, void)
452 {
453 auto nValue = rIdent.toInt32();
454 if (nValue != mxMetric->get_value(FieldUnit::PERCENT))
455 {
456 mxMetric->set_value(nValue, FieldUnit::PERCENT);
457 implModifyHdl(*mxMetric);
458 }
459 }
460
setValue(const Any & rValue,const OUString &)461 void SdTransparencyPropertyBox::setValue(const Any& rValue, const OUString&)
462 {
463 if (mxMetric)
464 {
465 double fValue = 0.0;
466 rValue >>= fValue;
467 ::tools::Long nValue = static_cast<::tools::Long>(fValue * 100);
468 mxMetric->set_value(nValue, FieldUnit::PERCENT);
469 updateMenu();
470 }
471 }
472
getValue()473 Any SdTransparencyPropertyBox::getValue()
474 {
475 return makeAny(static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0);
476 }
477
478 namespace {
479
480 class SdRotationPropertyBox : public SdPropertySubControl
481 {
482 public:
483 SdRotationPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
484
485 virtual Any getValue() override;
486 virtual void setValue( const Any& rValue, const OUString& ) override;
487
488 DECL_LINK(implMenuSelectHdl, const OString&, void);
489 DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);
490
491 void updateMenu();
492
493 private:
494 Link<LinkParamNone*,void> maModifyHdl;
495
496 std::unique_ptr<weld::MetricSpinButton> mxMetric;
497 std::unique_ptr<weld::MenuButton> mxControl;
498 };
499
500 }
501
SdRotationPropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)502 SdRotationPropertyBox::SdRotationPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
503 : SdPropertySubControl(pParent)
504 , maModifyHdl(rModifyHdl)
505 , mxMetric(mxBuilder->weld_metric_spin_button("rotate", FieldUnit::DEGREE))
506 , mxControl(mxBuilder->weld_menu_button("rotatemenu"))
507 {
508 mxMetric->connect_value_changed(LINK( this, SdRotationPropertyBox, implModifyHdl));
509 mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_ROTATIONPROPERTYBOX);
510 mxMetric->show();
511 pLabel->set_mnemonic_widget(&mxMetric->get_widget());
512
513 mxControl->connect_selected(LINK(this, SdRotationPropertyBox, implMenuSelectHdl));
514 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_ROTATIONPROPERTYBOX);
515 mxControl->show();
516
517 setValue(rValue, OUString());
518 }
519
updateMenu()520 void SdRotationPropertyBox::updateMenu()
521 {
522 sal_Int64 nValue = mxMetric->get_value(FieldUnit::DEGREE);
523 bool bDirection = nValue >= 0;
524 nValue = (nValue < 0 ? -nValue : nValue);
525
526 mxControl->set_item_active("90", nValue == 90);
527 mxControl->set_item_active("180", nValue == 180);
528 mxControl->set_item_active("360", nValue == 360);
529 mxControl->set_item_active("720", nValue == 720);
530
531 mxControl->set_item_active("closewise", bDirection);
532 mxControl->set_item_active("counterclock", !bDirection);
533 }
534
IMPL_LINK_NOARG(SdRotationPropertyBox,implModifyHdl,weld::MetricSpinButton &,void)535 IMPL_LINK_NOARG(SdRotationPropertyBox, implModifyHdl, weld::MetricSpinButton&, void)
536 {
537 updateMenu();
538 maModifyHdl.Call(nullptr);
539 }
540
IMPL_LINK(SdRotationPropertyBox,implMenuSelectHdl,const OString &,rIdent,void)541 IMPL_LINK(SdRotationPropertyBox, implMenuSelectHdl, const OString&, rIdent, void)
542 {
543 auto nValue = mxMetric->get_value(FieldUnit::DEGREE);
544 bool bDirection = nValue >= 0;
545 nValue = (nValue < 0 ? -nValue : nValue);
546
547 if (rIdent == "clockwise")
548 bDirection = true;
549 else if (rIdent == "counterclock")
550 bDirection = false;
551 else
552 nValue = rIdent.toInt32();
553
554 if( !bDirection )
555 nValue = -nValue;
556
557 if (nValue != mxMetric->get_value(FieldUnit::DEGREE))
558 {
559 mxMetric->set_value(nValue, FieldUnit::DEGREE);
560 implModifyHdl(*mxMetric);
561 }
562 }
563
setValue(const Any & rValue,const OUString &)564 void SdRotationPropertyBox::setValue( const Any& rValue, const OUString& )
565 {
566 if (mxMetric)
567 {
568 double fValue = 0.0;
569 rValue >>= fValue;
570 ::tools::Long nValue = static_cast<::tools::Long>(fValue);
571 mxMetric->set_value(nValue, FieldUnit::DEGREE);
572 updateMenu();
573 }
574 }
575
getValue()576 Any SdRotationPropertyBox::getValue()
577 {
578 return makeAny(static_cast<double>(mxMetric->get_value(FieldUnit::DEGREE)));
579 }
580
581 namespace {
582
583 class SdScalePropertyBox : public SdPropertySubControl
584 {
585 public:
586 SdScalePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
587
588 virtual Any getValue() override;
589 virtual void setValue( const Any& rValue, const OUString& ) override;
590
591 DECL_LINK(implMenuSelectHdl, const OString&, void);
592 DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);
593
594 void updateMenu();
595
596 private:
597 Link<LinkParamNone*,void> maModifyHdl;
598 int mnDirection;
599
600 std::unique_ptr<weld::MetricSpinButton> mxMetric;
601 std::unique_ptr<weld::MenuButton> mxControl;
602 };
603
604 }
605
SdScalePropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)606 SdScalePropertyBox::SdScalePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
607 : SdPropertySubControl(pParent)
608 , maModifyHdl( rModifyHdl )
609 , mxMetric(mxBuilder->weld_metric_spin_button("scale", FieldUnit::PERCENT))
610 , mxControl(mxBuilder->weld_menu_button("scalemenu"))
611 {
612 mxControl->connect_selected(LINK(this, SdScalePropertyBox, implMenuSelectHdl));
613 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_SCALEPROPERTYBOX);
614 mxControl->show();
615
616 mxMetric->connect_value_changed(LINK(this, SdScalePropertyBox, implModifyHdl));
617 mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_SCALEPROPERTYBOX);
618 mxMetric->show();
619 pLabel->set_mnemonic_widget(&mxMetric->get_widget());
620
621 setValue(rValue, OUString());
622 }
623
updateMenu()624 void SdScalePropertyBox::updateMenu()
625 {
626 auto nValue = mxMetric->get_value(FieldUnit::PERCENT);
627
628 mxControl->set_item_active("25scale", nValue == 25);
629 mxControl->set_item_active("50scale", nValue == 50);
630 mxControl->set_item_active("150scale", nValue == 150);
631 mxControl->set_item_active("400scale", nValue == 400);
632
633 mxControl->set_item_active("hori", mnDirection == 1);
634 mxControl->set_item_active("vert", mnDirection == 2);
635 mxControl->set_item_active("both", mnDirection == 3);
636 }
637
IMPL_LINK_NOARG(SdScalePropertyBox,implModifyHdl,weld::MetricSpinButton &,void)638 IMPL_LINK_NOARG(SdScalePropertyBox, implModifyHdl, weld::MetricSpinButton&, void)
639 {
640 updateMenu();
641 maModifyHdl.Call(nullptr);
642 }
643
IMPL_LINK(SdScalePropertyBox,implMenuSelectHdl,const OString &,rIdent,void)644 IMPL_LINK(SdScalePropertyBox, implMenuSelectHdl, const OString&, rIdent, void)
645 {
646 auto nValue = mxMetric->get_value(FieldUnit::PERCENT);
647
648 int nDirection = mnDirection;
649
650 if (rIdent == "hori")
651 nDirection = 1;
652 else if (rIdent == "vert")
653 nDirection = 2;
654 else if (rIdent == "both")
655 nDirection = 3;
656 else
657 nValue = rIdent.toInt32(); // Getting here indicates a UI bug and should be handled better
658
659 bool bModified = false;
660
661 if( nDirection != mnDirection )
662 {
663 mnDirection = nDirection;
664 bModified = true;
665 }
666
667 if (nValue != mxMetric->get_value(FieldUnit::PERCENT))
668 {
669 mxMetric->set_value(nValue, FieldUnit::PERCENT);
670 bModified = true;
671 }
672
673 if(bModified)
674 {
675 implModifyHdl(*mxMetric);
676 updateMenu();
677 }
678 }
679
setValue(const Any & rValue,const OUString &)680 void SdScalePropertyBox::setValue(const Any& rValue, const OUString&)
681 {
682 if (!mxMetric)
683 return;
684
685 ValuePair aValues;
686 rValue >>= aValues;
687
688 double fValue1 = 0.0;
689 double fValue2 = 0.0;
690
691 aValues.First >>= fValue1;
692 aValues.Second >>= fValue2;
693
694 // 'Size' drop down menu set by mnDirection when loading Grow and Shrink Animation
695 // Shouldn't compare a float directly to zero... should be fixed with delta epsilon compare
696 // Might be better to just have a flag in the content.xml for this
697 if( (fValue1 == 0.0) && (fValue2 == 0.0) )
698 mnDirection = 3; // assume 'Both' scaling option when both are zero
699 else if( (fValue1 != 0.0) && (fValue2 == 0.0) )
700 mnDirection = 1;
701 else if( (fValue1 == 0.0) && (fValue2 != 0.0) )
702 mnDirection = 2;
703 else
704 mnDirection = 3;
705
706 // Grow and Shrink Animation is a relative change with value stored in content.xml under tag
707 // smil:by=*,*
708 // An offset of 1 must be added to properly translate from content.xml to UI value displayed
709 // e.g. if in content.xml smil:by=0.5,0.5 then 1 + (0.5,0.5) = (1.5,1.5) => grow by 150% of the
710 // size horizontal and vertical
711 // e.g. if in content.xml smil:by=-0.5,-0.5 then 1 + (-0.5,-0.5) = (0.5,0.5) => shrink by 50%
712 // of the size horizontal and vertical
713 fValue1 += 1;
714 fValue2 += 1;
715
716 // Determine value from file for UI 'Size' field based on determined mnDirection
717 ::tools::Long nValue;
718 if( mnDirection == 1 )
719 nValue = static_cast<::tools::Long>(fValue1 * 100.0);
720 else if( mnDirection == 2 )
721 nValue = static_cast<::tools::Long>(fValue2 * 100.0);
722 else if( mnDirection == 3 ){
723 if (fValue1 >= fValue2)
724 nValue = static_cast<::tools::Long>(fValue1 * 100.0);
725 else
726 nValue = static_cast<::tools::Long>(fValue2 * 100.0);
727 }
728 else
729 nValue = static_cast<::tools::Long>(100.0); // default to 100% in UI if something goes wrong
730
731 mxMetric->set_value(nValue, FieldUnit::PERCENT);
732 updateMenu();
733 }
734
getValue()735 Any SdScalePropertyBox::getValue()
736 {
737 double fValue1 = static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0;
738
739 // Grow and Shrink Animation is a relative change with value stored in content.xml under tag
740 // smil:by=*,*
741 // An offset of 1 must be subtracted to properly translate UI value displayed and save to
742 // content.xml
743 // e.g. if UI value is 150% then 1.5 - 1 = 0.5 and is set to smil:by=0.5,0.5 in content.xml
744 // e.g. if UI value is 50% then 0.5 - 1 = -0.5 and is set to smil:by=-0.5,-0.5 in content.xml
745 fValue1 -= 1;
746
747 double fValue2 = fValue1;
748
749 // mnDirection set by 'Size' drop down menu and used to zero out either horizontal or vertical
750 // scaling depending on what option is selected
751 if( mnDirection == 1 )
752 fValue2 = 0.0;
753 else if( mnDirection == 2 )
754 fValue1 = 0.0;
755
756 ValuePair aValues;
757 aValues.First <<= fValue1;
758 aValues.Second <<= fValue2;
759
760 return makeAny( aValues );
761 }
762
763 namespace {
764
765 class SdFontStylePropertyBox : public SdPropertySubControl
766 {
767 public:
768 SdFontStylePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);
769
770 virtual Any getValue() override;
771 virtual void setValue( const Any& rValue, const OUString& ) override;
772
773 DECL_LINK(implMenuSelectHdl, const OString&, void);
774
775 void update();
776
777 private:
778 float mfFontWeight;
779 awt::FontSlant meFontSlant;
780 sal_Int16 mnFontUnderline;
781 Link<LinkParamNone*,void> maModifyHdl;
782
783 std::unique_ptr<weld::Entry> mxEdit;
784 std::unique_ptr<weld::MenuButton> mxControl;
785 };
786
787 }
788
SdFontStylePropertyBox(weld::Label * pLabel,weld::Container * pParent,const Any & rValue,const Link<LinkParamNone *,void> & rModifyHdl)789 SdFontStylePropertyBox::SdFontStylePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl )
790 : SdPropertySubControl(pParent)
791 , maModifyHdl( rModifyHdl )
792 , mxEdit(mxBuilder->weld_entry("entry"))
793 , mxControl(mxBuilder->weld_menu_button("entrymenu"))
794 {
795 mxEdit->set_text(SdResId(STR_CUSTOMANIMATION_SAMPLE));
796 mxEdit->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTSTYLEPROPERTYBOX);
797 pLabel->set_mnemonic_widget(mxEdit.get());
798 mxEdit->show();
799
800 mxControl->connect_selected(LINK(this, SdFontStylePropertyBox, implMenuSelectHdl));
801 mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTSTYLEPROPERTYBOX);
802 mxControl->show();
803
804 setValue(rValue, OUString());
805 }
806
update()807 void SdFontStylePropertyBox::update()
808 {
809 // update menu
810 mxControl->set_item_active("bold", mfFontWeight == awt::FontWeight::BOLD);
811 mxControl->set_item_active("italic", meFontSlant == awt::FontSlant_ITALIC);
812 mxControl->set_item_active("underline", mnFontUnderline != awt::FontUnderline::NONE );
813
814 // update sample edit
815 vcl::Font aFont(mxEdit->get_font());
816 aFont.SetWeight(mfFontWeight == awt::FontWeight::BOLD ? WEIGHT_BOLD : WEIGHT_NORMAL);
817 aFont.SetItalic(meFontSlant == awt::FontSlant_ITALIC ? ITALIC_NORMAL : ITALIC_NONE);
818 aFont.SetUnderline(mnFontUnderline == awt::FontUnderline::NONE ? LINESTYLE_NONE : LINESTYLE_SINGLE);
819 mxEdit->set_font(aFont);
820 }
821
IMPL_LINK(SdFontStylePropertyBox,implMenuSelectHdl,const OString &,rIdent,void)822 IMPL_LINK(SdFontStylePropertyBox, implMenuSelectHdl, const OString&, rIdent, void)
823 {
824 if (rIdent == "bold")
825 {
826 if( mfFontWeight == awt::FontWeight::BOLD )
827 mfFontWeight = awt::FontWeight::NORMAL;
828 else
829 mfFontWeight = awt::FontWeight::BOLD;
830 }
831 else if (rIdent == "italic")
832 {
833 if( meFontSlant == awt::FontSlant_ITALIC )
834 meFontSlant = awt::FontSlant_NONE;
835 else
836 meFontSlant = awt::FontSlant_ITALIC;
837 }
838 else if (rIdent == "underline")
839 {
840 if( mnFontUnderline == awt::FontUnderline::SINGLE )
841 mnFontUnderline = awt::FontUnderline::NONE;
842 else
843 mnFontUnderline = awt::FontUnderline::SINGLE;
844 }
845
846 update();
847 maModifyHdl.Call(nullptr);
848 }
849
setValue(const Any & rValue,const OUString &)850 void SdFontStylePropertyBox::setValue( const Any& rValue, const OUString& )
851 {
852 Sequence<Any> aValues;
853 rValue >>= aValues;
854
855 aValues[0] >>= mfFontWeight;
856 aValues[1] >>= meFontSlant;
857 aValues[2] >>= mnFontUnderline;
858
859 update();
860 }
861
getValue()862 Any SdFontStylePropertyBox::getValue()
863 {
864 Sequence<Any> aValues(3);
865 aValues[0] <<= mfFontWeight;
866 aValues[1] <<= meFontSlant;
867 aValues[2] <<= mnFontUnderline;
868 return makeAny( aValues );
869 }
870
871 class CustomAnimationEffectTabPage
872 {
873 public:
874 CustomAnimationEffectTabPage(weld::Container* pParent, weld::Window* pDialog, const STLPropertySet* pSet);
875
876 void update( STLPropertySet* pSet );
877 DECL_LINK(implSelectHdl, weld::ComboBox&, void);
878 DECL_LINK(implClickHdl, weld::Button&, void);
879 void implHdl(const weld::Widget*);
880
881 private:
882 void updateControlStates();
883 void fillSoundListBox();
884 void clearSoundListBox();
885 sal_Int32 getSoundObject( std::u16string_view rStr );
886 void openSoundFileDialog();
887 void onSoundPreview();
GetFrameWeld() const888 weld::Window* GetFrameWeld() const { return mpDialog; }
889
890 private:
891 ::std::vector< OUString > maSoundList;
892 bool mbHasText;
893 const STLPropertySet* mpSet;
894 css::uno::Reference<css::media::XPlayer> mxPlayer;
895
896 weld::Window* mpDialog;
897 std::unique_ptr<weld::Builder> mxBuilder;
898 std::unique_ptr<weld::Container> mxContainer;
899 std::unique_ptr<weld::Widget> mxSettings;
900 std::unique_ptr<weld::Label> mxFTProperty1;
901 std::unique_ptr<weld::Container> mxPlaceholderBox;
902 std::unique_ptr<weld::CheckButton> mxCBSmoothStart;
903 std::unique_ptr<weld::CheckButton> mxCBSmoothEnd;
904 std::unique_ptr<weld::Label> mxFTSound;
905 std::unique_ptr<weld::ComboBox> mxLBSound;
906 std::unique_ptr<weld::Button> mxPBSoundPreview;
907 std::unique_ptr<weld::Label> mxFTAfterEffect;
908 std::unique_ptr<weld::ComboBox> mxLBAfterEffect;
909 std::unique_ptr<weld::Label> mxFTDimColor;
910 std::unique_ptr<ColorListBox> mxCLBDimColor;
911 std::unique_ptr<weld::Label> mxFTTextAnim;
912 std::unique_ptr<weld::ComboBox> mxLBTextAnim;
913 std::unique_ptr<weld::MetricSpinButton> mxMFTextDelay;
914 std::unique_ptr<weld::Label> mxFTTextDelay;
915 std::unique_ptr<SdPropertySubControl> mxLBSubControl;
916 };
917
CustomAnimationEffectTabPage(weld::Container * pParent,weld::Window * pDialog,const STLPropertySet * pSet)918 CustomAnimationEffectTabPage::CustomAnimationEffectTabPage(weld::Container* pParent, weld::Window* pDialog, const STLPropertySet* pSet)
919 : mbHasText(false)
920 , mpSet(pSet)
921 , mpDialog(pDialog)
922 , mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationeffecttab.ui"))
923 , mxContainer(mxBuilder->weld_container("EffectTab"))
924 , mxSettings(mxBuilder->weld_widget("settings"))
925 , mxFTProperty1(mxBuilder->weld_label("prop_label1"))
926 , mxPlaceholderBox(mxBuilder->weld_container("placeholder"))
927 , mxCBSmoothStart(mxBuilder->weld_check_button("smooth_start"))
928 , mxCBSmoothEnd(mxBuilder->weld_check_button("smooth_end"))
929 , mxFTSound(mxBuilder->weld_label("sound_label"))
930 , mxLBSound(mxBuilder->weld_combo_box("sound_list"))
931 , mxPBSoundPreview(mxBuilder->weld_button("sound_preview"))
932 , mxFTAfterEffect(mxBuilder->weld_label("aeffect_label"))
933 , mxLBAfterEffect(mxBuilder->weld_combo_box("aeffect_list"))
934 , mxFTDimColor(mxBuilder->weld_label("dim_color_label"))
935 , mxCLBDimColor(new ColorListBox(mxBuilder->weld_menu_button("dim_color_list"), [pDialog]{ return pDialog; }))
936 , mxFTTextAnim(mxBuilder->weld_label("text_animation_label"))
937 , mxLBTextAnim(mxBuilder->weld_combo_box("text_animation_list"))
938 , mxMFTextDelay(mxBuilder->weld_metric_spin_button("text_delay", FieldUnit::PERCENT))
939 , mxFTTextDelay(mxBuilder->weld_label("text_delay_label"))
940 {
941 mxCLBDimColor->SelectEntry(COL_BLACK);
942
943 // fill the soundbox
944 fillSoundListBox();
945
946 mxLBSound->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));
947 mxPBSoundPreview->connect_clicked(LINK(this, CustomAnimationEffectTabPage, implClickHdl));
948
949 // only show settings if all selected effects have the same preset-id
950 if( pSet->getPropertyState( nHandlePresetId ) != STLPropertyState::Ambiguous )
951 {
952 OUString aPresetId;
953 pSet->getPropertyValue( nHandlePresetId ) >>= aPresetId;
954
955 // property 1
956
957 if( pSet->getPropertyState( nHandleProperty1Type ) != STLPropertyState::Ambiguous )
958 {
959 sal_Int32 nType = 0;
960 pSet->getPropertyValue( nHandleProperty1Type ) >>= nType;
961
962 if( nType != nPropertyTypeNone )
963 {
964 // set ui name for property at fixed text
965 OUString aPropertyName( getPropertyName( nType ) );
966
967 if( !aPropertyName.isEmpty() )
968 {
969 mxSettings->show();
970 mxFTProperty1->set_label(aPropertyName);
971 }
972
973 // get property value
974 const Any aValue( pSet->getPropertyValue( nHandleProperty1Value ) );
975
976 // create property sub control
977 mxLBSubControl = SdPropertySubControl::create(nType, mxFTProperty1.get(), mxPlaceholderBox.get(), mpDialog, aValue, aPresetId, Link<LinkParamNone*,void>());
978 }
979 }
980
981 mxFTProperty1->set_sensitive(mxPlaceholderBox->get_sensitive());
982
983 // accelerate & decelerate
984
985 if( pSet->getPropertyState( nHandleAccelerate ) == STLPropertyState::Direct )
986 {
987 mxCBSmoothStart->show();
988 mxCBSmoothEnd->show();
989
990 double fTemp = 0.0;
991 pSet->getPropertyValue( nHandleAccelerate ) >>= fTemp;
992 mxCBSmoothStart->set_active( fTemp > 0.0 );
993
994 pSet->getPropertyValue( nHandleDecelerate ) >>= fTemp;
995 mxCBSmoothEnd->set_active( fTemp > 0.0 );
996 }
997 }
998
999 // init after effect controls
1000
1001 mxLBAfterEffect->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));
1002 mxLBTextAnim->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));
1003
1004 if( (pSet->getPropertyState( nHandleHasAfterEffect ) != STLPropertyState::Ambiguous) &&
1005 (pSet->getPropertyState( nHandleAfterEffectOnNextEffect ) != STLPropertyState::Ambiguous) &&
1006 (pSet->getPropertyState( nHandleDimColor ) != STLPropertyState::Ambiguous))
1007 {
1008 bool bHasAfterEffect = false;
1009 pSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect;
1010
1011 sal_Int32 nPos = 0;
1012 if( bHasAfterEffect )
1013 {
1014 nPos++;
1015
1016 bool bAfterEffectOnNextClick = false;
1017 pSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextClick;
1018 Any aDimColor( pSet->getPropertyValue( nHandleDimColor ) );
1019
1020 if( aDimColor.hasValue() )
1021 {
1022 Color aColor;
1023 aDimColor >>= aColor;
1024 mxCLBDimColor->SelectEntry(aColor);
1025 }
1026 else
1027 {
1028 nPos++;
1029 if( bAfterEffectOnNextClick )
1030 nPos++;
1031 }
1032 }
1033
1034 mxLBAfterEffect->set_active(nPos);
1035 }
1036
1037 if( pSet->getPropertyState( nHandleHasText ) != STLPropertyState::Ambiguous )
1038 pSet->getPropertyValue( nHandleHasText ) >>= mbHasText;
1039
1040 if( mbHasText )
1041 {
1042 if( pSet->getPropertyState( nHandleIterateType ) != STLPropertyState::Ambiguous)
1043 {
1044 int nPos = -1;
1045
1046 sal_Int32 nIterateType = 0;
1047 pSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
1048 switch( nIterateType )
1049 {
1050 case TextAnimationType::BY_PARAGRAPH: nPos = 0; break;
1051 case TextAnimationType::BY_WORD: nPos = 1; break;
1052 case TextAnimationType::BY_LETTER: nPos = 2; break;
1053 }
1054
1055 mxLBTextAnim->set_active(nPos);
1056 }
1057
1058 if( pSet->getPropertyState( nHandleIterateInterval ) != STLPropertyState::Default )
1059 {
1060 double fIterateInterval = 0.0;
1061 pSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
1062 mxMFTextDelay->set_value(static_cast<::tools::Long>(fIterateInterval*10), FieldUnit::NONE);
1063 }
1064 }
1065 else
1066 {
1067 mxFTTextAnim->set_sensitive(false);
1068 mxLBTextAnim->set_sensitive(false);
1069 mxMFTextDelay->set_sensitive(false);
1070 mxFTTextDelay->set_sensitive(false);
1071
1072 }
1073
1074 if( pSet->getPropertyState( nHandleSoundURL ) != STLPropertyState::Ambiguous )
1075 {
1076 sal_Int32 nPos = 0;
1077
1078 const Any aValue( pSet->getPropertyValue( nHandleSoundURL ) );
1079
1080 if( aValue.getValueType() == ::cppu::UnoType<sal_Bool>::get() )
1081 {
1082 nPos = 1;
1083 }
1084 else
1085 {
1086 OUString aSoundURL;
1087 aValue >>= aSoundURL;
1088
1089 if( !aSoundURL.isEmpty() )
1090 {
1091 sal_uLong i;
1092 for( i = 0; i < maSoundList.size(); i++ )
1093 {
1094 OUString aString = maSoundList[ i ];
1095 if( aString == aSoundURL )
1096 {
1097 nPos = static_cast<sal_Int32>(i)+2;
1098 break;
1099 }
1100 }
1101
1102 if( nPos == 0 )
1103 {
1104 nPos = static_cast<sal_Int32>(maSoundList.size())+2;
1105 maSoundList.push_back( aSoundURL );
1106 INetURLObject aURL( aSoundURL );
1107 mxLBSound->insert_text(nPos, aURL.GetBase());
1108 }
1109 }
1110 }
1111
1112 if( nPos != -1)
1113 mxLBSound->set_active(nPos);
1114 }
1115
1116 updateControlStates();
1117
1118 }
1119
updateControlStates()1120 void CustomAnimationEffectTabPage::updateControlStates()
1121 {
1122 auto nPos = mxLBAfterEffect->get_active();
1123 mxCLBDimColor->set_sensitive( nPos == 1 );
1124 mxFTDimColor->set_sensitive( nPos == 1 );
1125
1126 if( mbHasText )
1127 {
1128 nPos = mxLBTextAnim->get_active();
1129 mxMFTextDelay->set_sensitive( nPos != 0 );
1130 mxFTTextDelay->set_sensitive( nPos != 0 );
1131 }
1132
1133 if (comphelper::LibreOfficeKit::isActive())
1134 {
1135 mxFTSound->hide();
1136 mxLBSound->hide();
1137 mxPBSoundPreview->hide();
1138 }
1139 else
1140 {
1141 nPos = mxLBSound->get_active();
1142 mxPBSoundPreview->set_sensitive( nPos >= 2 );
1143 }
1144
1145 }
1146
IMPL_LINK(CustomAnimationEffectTabPage,implClickHdl,weld::Button &,rBtn,void)1147 IMPL_LINK(CustomAnimationEffectTabPage, implClickHdl, weld::Button&, rBtn, void)
1148 {
1149 implHdl(&rBtn);
1150 }
1151
IMPL_LINK(CustomAnimationEffectTabPage,implSelectHdl,weld::ComboBox &,rListBox,void)1152 IMPL_LINK(CustomAnimationEffectTabPage, implSelectHdl, weld::ComboBox&, rListBox, void)
1153 {
1154 implHdl(&rListBox);
1155 }
1156
implHdl(const weld::Widget * pControl)1157 void CustomAnimationEffectTabPage::implHdl(const weld::Widget* pControl)
1158 {
1159 if (pControl == mxLBTextAnim.get())
1160 {
1161 if (mxMFTextDelay->get_value(FieldUnit::NONE) == 0)
1162 mxMFTextDelay->set_value(100, FieldUnit::NONE);
1163 }
1164 else if (pControl == mxLBSound.get())
1165 {
1166 auto nPos = mxLBSound->get_active();
1167 if (nPos == (mxLBSound->get_count() - 1))
1168 {
1169 openSoundFileDialog();
1170 }
1171 }
1172 else if (pControl == mxPBSoundPreview.get())
1173 {
1174 onSoundPreview();
1175 }
1176
1177 updateControlStates();
1178 }
1179
update(STLPropertySet * pSet)1180 void CustomAnimationEffectTabPage::update( STLPropertySet* pSet )
1181 {
1182 if (mxLBSubControl)
1183 {
1184 Any aNewValue(mxLBSubControl->getValue());
1185 Any aOldValue;
1186 if( mpSet->getPropertyState( nHandleProperty1Value ) != STLPropertyState::Ambiguous)
1187 aOldValue = mpSet->getPropertyValue( nHandleProperty1Value );
1188
1189 if( aOldValue != aNewValue )
1190 pSet->setPropertyValue( nHandleProperty1Value, aNewValue );
1191 }
1192
1193 if (mxCBSmoothStart->get_visible())
1194 {
1195 // set selected value for accelerate if different than in original set
1196
1197 double fTemp = mxCBSmoothStart->get_active() ? 0.5 : 0.0;
1198
1199 double fOldTemp = 0.0;
1200 if(mpSet->getPropertyState( nHandleAccelerate ) != STLPropertyState::Ambiguous)
1201 mpSet->getPropertyValue( nHandleAccelerate ) >>= fOldTemp;
1202 else
1203 fOldTemp = -2.0;
1204
1205 if( fOldTemp != fTemp )
1206 pSet->setPropertyValue( nHandleAccelerate, makeAny( fTemp ) );
1207
1208 // set selected value for decelerate if different than in original set
1209 fTemp = mxCBSmoothEnd->get_active() ? 0.5 : 0.0;
1210
1211 if(mpSet->getPropertyState( nHandleDecelerate ) != STLPropertyState::Ambiguous)
1212 mpSet->getPropertyValue( nHandleDecelerate ) >>= fOldTemp;
1213 else
1214 fOldTemp = -2.0;
1215
1216 if( fOldTemp != fTemp )
1217 pSet->setPropertyValue( nHandleDecelerate, makeAny( fTemp ) );
1218 }
1219
1220 auto nPos = mxLBAfterEffect->get_active();
1221 if (nPos != -1)
1222 {
1223 bool bAfterEffect = nPos != 0;
1224
1225 bool bOldAfterEffect = false;
1226
1227 if(mpSet->getPropertyState( nHandleHasAfterEffect ) != STLPropertyState::Ambiguous)
1228 mpSet->getPropertyValue( nHandleHasAfterEffect ) >>= bOldAfterEffect;
1229 else
1230 bOldAfterEffect = !bAfterEffect;
1231
1232 if( bOldAfterEffect != bAfterEffect )
1233 pSet->setPropertyValue( nHandleHasAfterEffect, makeAny( bAfterEffect ) );
1234
1235 Any aDimColor;
1236 if( nPos == 1 )
1237 {
1238 Color aSelectedColor = mxCLBDimColor->GetSelectEntryColor();
1239 aDimColor <<= aSelectedColor.GetRGBColor();
1240 }
1241
1242 if( (mpSet->getPropertyState( nHandleDimColor ) == STLPropertyState::Ambiguous) ||
1243 (mpSet->getPropertyValue( nHandleDimColor ) != aDimColor) )
1244 pSet->setPropertyValue( nHandleDimColor, aDimColor );
1245
1246 bool bAfterEffectOnNextEffect = nPos != 2;
1247 bool bOldAfterEffectOnNextEffect = !bAfterEffectOnNextEffect;
1248
1249 if( mpSet->getPropertyState( nHandleAfterEffectOnNextEffect ) != STLPropertyState::Ambiguous)
1250 mpSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bOldAfterEffectOnNextEffect;
1251
1252 if( bAfterEffectOnNextEffect != bOldAfterEffectOnNextEffect )
1253 pSet->setPropertyValue( nHandleAfterEffectOnNextEffect, makeAny( bAfterEffectOnNextEffect ) );
1254 }
1255
1256 nPos = mxLBTextAnim->get_active();
1257 if (nPos != -1)
1258 {
1259 sal_Int16 nIterateType;
1260
1261 switch( nPos )
1262 {
1263 case 1: nIterateType = TextAnimationType::BY_WORD; break;
1264 case 2: nIterateType = TextAnimationType::BY_LETTER; break;
1265 default:
1266 nIterateType = TextAnimationType::BY_PARAGRAPH;
1267 }
1268
1269 sal_Int16 nOldIterateType = nIterateType-1;
1270
1271 if(mpSet->getPropertyState( nHandleIterateType ) != STLPropertyState::Ambiguous)
1272 mpSet->getPropertyValue( nHandleIterateType ) >>= nOldIterateType;
1273
1274 if( nIterateType != nOldIterateType )
1275 pSet->setPropertyValue( nHandleIterateType, makeAny( nIterateType ) );
1276 }
1277
1278 {
1279 double fIterateInterval = static_cast<double>(mxMFTextDelay->get_value(FieldUnit::NONE)) / 10;
1280 double fOldIterateInterval = -1.0;
1281
1282 if( mpSet->getPropertyState( nHandleIterateInterval ) != STLPropertyState::Ambiguous )
1283 mpSet->getPropertyValue( nHandleIterateInterval ) >>= fOldIterateInterval;
1284
1285 if( fIterateInterval != fOldIterateInterval )
1286 pSet->setPropertyValue( nHandleIterateInterval, makeAny( fIterateInterval ) );
1287 }
1288
1289 nPos = mxLBSound->get_active();
1290 if (nPos == -1)
1291 return;
1292
1293 Any aNewSoundURL, aOldSoundURL( makeAny( sal_Int32(0) ) );
1294
1295 if( nPos == 0 )
1296 {
1297 // 0 means no sound, so leave any empty
1298 }
1299 else if( nPos == 1 )
1300 {
1301 // this means stop sound
1302 aNewSoundURL <<= true;
1303 }
1304 else
1305 {
1306 OUString aSoundURL( maSoundList[ nPos-2 ] );
1307 aNewSoundURL <<= aSoundURL;
1308 }
1309
1310 if( mpSet->getPropertyState( nHandleSoundURL ) != STLPropertyState::Ambiguous )
1311 aOldSoundURL = mpSet->getPropertyValue( nHandleSoundURL );
1312
1313 if( aNewSoundURL != aOldSoundURL )
1314 pSet->setPropertyValue( nHandleSoundURL, aNewSoundURL );
1315 }
1316
fillSoundListBox()1317 void CustomAnimationEffectTabPage::fillSoundListBox()
1318 {
1319 GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS, maSoundList );
1320 GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS, maSoundList );
1321
1322 mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_NO_SOUND) );
1323 mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_STOP_PREVIOUS_SOUND) );
1324 for(const OUString & rString : maSoundList)
1325 {
1326 INetURLObject aURL( rString );
1327 mxLBSound->append_text( aURL.GetBase() );
1328 }
1329 mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_BROWSE_SOUND) );
1330 }
1331
clearSoundListBox()1332 void CustomAnimationEffectTabPage::clearSoundListBox()
1333 {
1334 maSoundList.clear();
1335 mxLBSound->clear();
1336 }
1337
getSoundObject(std::u16string_view rStr)1338 sal_Int32 CustomAnimationEffectTabPage::getSoundObject( std::u16string_view rStr )
1339 {
1340 size_t i;
1341 const size_t nCount = maSoundList.size();
1342 for( i = 0; i < nCount; i++ )
1343 {
1344 if( maSoundList[ i ].equalsIgnoreAsciiCase(rStr) )
1345 return i+2;
1346 }
1347
1348 return -1;
1349 }
1350
openSoundFileDialog()1351 void CustomAnimationEffectTabPage::openSoundFileDialog()
1352 {
1353 SdOpenSoundFileDialog aFileDialog(GetFrameWeld());
1354
1355 bool bValidSoundFile = false;
1356 bool bQuitLoop = false;
1357 ::tools::Long nPos = 0;
1358
1359 while( !bQuitLoop && (aFileDialog.Execute() == ERRCODE_NONE) )
1360 {
1361 OUString aFile = aFileDialog.GetPath();
1362 nPos = getSoundObject( aFile );
1363
1364 if( nPos < 0 ) // not in Soundliste
1365 {
1366 // try to insert in Gallery
1367 if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS, aFile ) )
1368 {
1369 clearSoundListBox();
1370 fillSoundListBox();
1371
1372 nPos = getSoundObject( aFile );
1373 DBG_ASSERT( nPos >= 0, "sd::CustomAnimationEffectTabPage::openSoundFileDialog(), Recently inserted sound not in list!" );
1374
1375 bValidSoundFile=true;
1376 bQuitLoop=true;
1377 }
1378 else
1379 {
1380 OUString aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE));
1381 aStrWarning = aStrWarning.replaceFirst("%", aFile);
1382 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
1383 VclMessageType::Warning, VclButtonsType::NONE,
1384 aStrWarning));
1385 xWarn->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY);
1386 xWarn->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
1387 bQuitLoop = xWarn->run() != RET_RETRY;
1388
1389 bValidSoundFile=false;
1390 }
1391 }
1392 else
1393 {
1394 bValidSoundFile=true;
1395 bQuitLoop=true;
1396 }
1397 }
1398
1399 if( !bValidSoundFile )
1400 nPos = 0;
1401
1402 mxLBSound->set_active(nPos);
1403 }
1404
onSoundPreview()1405 void CustomAnimationEffectTabPage::onSoundPreview()
1406 {
1407 #if HAVE_FEATURE_AVMEDIA
1408 const auto nPos = mxLBSound->get_active();
1409
1410 if( nPos >= 2 ) try
1411 {
1412 const OUString aSoundURL( maSoundList[ nPos-2 ] );
1413 mxPlayer.set( avmedia::MediaWindow::createPlayer( aSoundURL, "" ), uno::UNO_SET_THROW );
1414 mxPlayer->start();
1415 }
1416 catch( uno::Exception& )
1417 {
1418 TOOLS_WARN_EXCEPTION( "sd", "CustomAnimationEffectTabPage::onSoundPreview()" );
1419 }
1420 #endif
1421 }
1422
1423 class CustomAnimationDurationTabPage
1424 {
1425 public:
1426 CustomAnimationDurationTabPage(weld::Container* pParent, const STLPropertySet* pSet);
1427
1428 void update( STLPropertySet* pSet );
1429
1430 DECL_LINK(implControlHdl, weld::ComboBox&, void);
1431 DECL_LINK(DurationModifiedHdl, weld::MetricSpinButton&, void);
1432
1433 private:
1434 const STLPropertySet* mpSet;
1435
1436 std::unique_ptr<weld::Builder> mxBuilder;
1437 std::unique_ptr<weld::Container> mxContainer;
1438 std::unique_ptr<weld::Label> mxFTStart;
1439 std::unique_ptr<weld::ComboBox> mxLBStart;
1440 std::unique_ptr<weld::Label> mxFTStartDelay;
1441 std::unique_ptr<weld::MetricSpinButton> mxMFStartDelay;
1442 std::unique_ptr<weld::Label> mxFTDuration;
1443 std::unique_ptr<weld::MetricSpinButton> mxCBXDuration;
1444 std::unique_ptr<weld::Label> mxFTRepeat;
1445 std::unique_ptr<weld::ComboBox> mxCBRepeat;
1446 std::unique_ptr<weld::CheckButton> mxCBXRewind;
1447 std::unique_ptr<weld::RadioButton> mxRBClickSequence;
1448 std::unique_ptr<weld::RadioButton> mxRBInteractive;
1449 std::unique_ptr<weld::ComboBox> mxLBTrigger;
1450 };
1451
CustomAnimationDurationTabPage(weld::Container * pParent,const STLPropertySet * pSet)1452 CustomAnimationDurationTabPage::CustomAnimationDurationTabPage(weld::Container* pParent, const STLPropertySet* pSet)
1453 : mpSet(pSet)
1454 , mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationtimingtab.ui"))
1455 , mxContainer(mxBuilder->weld_container("TimingTab"))
1456 , mxFTStart(mxBuilder->weld_label("start_label"))
1457 , mxLBStart(mxBuilder->weld_combo_box("start_list"))
1458 , mxFTStartDelay(mxBuilder->weld_label("delay_label"))
1459 , mxMFStartDelay(mxBuilder->weld_metric_spin_button("delay_value", FieldUnit::SECOND))
1460 , mxFTDuration(mxBuilder->weld_label("duration_label"))
1461 , mxCBXDuration(mxBuilder->weld_metric_spin_button("anim_duration", FieldUnit::SECOND))
1462 , mxFTRepeat(mxBuilder->weld_label("repeat_label"))
1463 , mxCBRepeat(mxBuilder->weld_combo_box("repeat_list"))
1464 , mxCBXRewind(mxBuilder->weld_check_button("rewind"))
1465 , mxRBClickSequence(mxBuilder->weld_radio_button("rb_click_sequence"))
1466 , mxRBInteractive(mxBuilder->weld_radio_button("rb_interactive"))
1467 , mxLBTrigger(mxBuilder->weld_combo_box("trigger_list"))
1468 {
1469 mxLBTrigger->set_size_request(mxLBTrigger->get_approximate_digit_width() * 20, -1);
1470
1471 fillRepeatComboBox(*mxCBRepeat);
1472
1473 mxLBTrigger->connect_changed(LINK(this, CustomAnimationDurationTabPage, implControlHdl));
1474 mxCBXDuration->connect_value_changed(LINK( this, CustomAnimationDurationTabPage, DurationModifiedHdl));
1475
1476 if( pSet->getPropertyState( nHandleStart ) != STLPropertyState::Ambiguous )
1477 {
1478 sal_Int16 nStart = 0;
1479 pSet->getPropertyValue( nHandleStart ) >>= nStart;
1480 sal_Int32 nPos = 0;
1481 switch( nStart )
1482 {
1483 case EffectNodeType::WITH_PREVIOUS: nPos = 1; break;
1484 case EffectNodeType::AFTER_PREVIOUS: nPos = 2; break;
1485 }
1486 mxLBStart->set_active(nPos);
1487 }
1488
1489 if( pSet->getPropertyState( nHandleBegin ) != STLPropertyState::Ambiguous )
1490 {
1491 double fBegin = 0.0;
1492 pSet->getPropertyValue( nHandleBegin ) >>= fBegin;
1493 mxMFStartDelay->set_value(static_cast<::tools::Long>(fBegin*10), FieldUnit::NONE);
1494 }
1495
1496 if( pSet->getPropertyState( nHandleDuration ) != STLPropertyState::Ambiguous )
1497 {
1498 double fDuration = 0.0;
1499 pSet->getPropertyValue( nHandleDuration ) >>= fDuration;
1500
1501 if( fDuration == 0.001 )
1502 {
1503 mxFTDuration->set_sensitive(false);
1504 mxCBXDuration->set_sensitive(false);
1505 mxFTRepeat->set_sensitive(false);
1506 mxCBRepeat->set_sensitive(false);
1507 mxCBXRewind->set_sensitive(false);
1508 }
1509 else
1510 {
1511 mxCBXDuration->set_value(fDuration * 100.0, FieldUnit::NONE);
1512 }
1513 }
1514
1515 if( pSet->getPropertyState( nHandleRepeat ) != STLPropertyState::Ambiguous )
1516 {
1517 Any aRepeatCount( pSet->getPropertyValue( nHandleRepeat ) );
1518 if( (aRepeatCount.getValueType() == ::cppu::UnoType<double>::get()) || !aRepeatCount.hasValue() )
1519 {
1520 double fRepeat = 0.0;
1521 if( aRepeatCount.hasValue() )
1522 aRepeatCount >>= fRepeat;
1523
1524 auto nPos = -1;
1525
1526 if( fRepeat == 0 )
1527 nPos = 0;
1528 else if( fRepeat == 2.0 )
1529 nPos = 1;
1530 else if( fRepeat == 3.0 )
1531 nPos = 2;
1532 else if( fRepeat == 4.0 )
1533 nPos = 3;
1534 else if( fRepeat == 5.0 )
1535 nPos = 4;
1536 else if( fRepeat == 10.0 )
1537 nPos = 5;
1538
1539 if (nPos != -1)
1540 mxCBRepeat->set_active(nPos);
1541 else
1542 mxCBRepeat->set_entry_text(OUString::number(fRepeat));
1543 }
1544 else if( aRepeatCount.getValueType() == ::cppu::UnoType<Timing>::get() )
1545 {
1546 Any aEnd;
1547 if( pSet->getPropertyState( nHandleEnd ) != STLPropertyState::Ambiguous )
1548 aEnd = pSet->getPropertyValue( nHandleEnd );
1549
1550 mxCBRepeat->set_active(aEnd.hasValue() ? 6 : 7);
1551 }
1552 }
1553
1554 if( pSet->getPropertyState( nHandleRewind ) != STLPropertyState::Ambiguous )
1555 {
1556 sal_Int16 nFill = 0;
1557 if( pSet->getPropertyValue( nHandleRewind ) >>= nFill )
1558 {
1559 mxCBXRewind->set_active(nFill == AnimationFill::REMOVE);
1560 }
1561 else
1562 {
1563 mxCBXRewind->set_state(TRISTATE_INDET);
1564 }
1565 }
1566
1567 Reference< XShape > xTrigger;
1568
1569 if( pSet->getPropertyState( nHandleTrigger ) != STLPropertyState::Ambiguous )
1570 {
1571 pSet->getPropertyValue( nHandleTrigger ) >>= xTrigger;
1572
1573 mxRBInteractive->set_active(xTrigger.is());
1574 mxRBClickSequence->set_active(!xTrigger.is());
1575 }
1576
1577 Reference< XDrawPage > xCurrentPage;
1578 pSet->getPropertyValue( nHandleCurrentPage ) >>= xCurrentPage;
1579 if( !xCurrentPage.is() )
1580 return;
1581
1582 static const OUStringLiteral aStrIsEmptyPresObj( u"IsEmptyPresentationObject" );
1583
1584 sal_Int32 nShape, nCount = xCurrentPage->getCount();
1585 for( nShape = 0; nShape < nCount; nShape++ )
1586 {
1587 Reference< XShape > xShape( xCurrentPage->getByIndex( nShape ), UNO_QUERY );
1588
1589 if( !xShape.is() )
1590 continue;
1591
1592 Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1593 if( xSet.is() && xSet->getPropertySetInfo()->hasPropertyByName( aStrIsEmptyPresObj ) )
1594 {
1595 bool bIsEmpty = false;
1596 xSet->getPropertyValue( aStrIsEmptyPresObj ) >>= bIsEmpty;
1597 if( bIsEmpty )
1598 continue;
1599 }
1600
1601 OUString aDescription( getShapeDescription( xShape, true ) );
1602 mxLBTrigger->append(OUString::number(nShape), aDescription);
1603 auto nPos = mxLBTrigger->get_count() - 1;
1604 if (xShape == xTrigger)
1605 mxLBTrigger->set_active(nPos);
1606 }
1607 }
1608
IMPL_LINK_NOARG(CustomAnimationDurationTabPage,implControlHdl,weld::ComboBox &,void)1609 IMPL_LINK_NOARG(CustomAnimationDurationTabPage, implControlHdl, weld::ComboBox&, void)
1610 {
1611 mxRBInteractive->set_active(true);
1612 assert(!mxRBClickSequence->get_active());
1613 }
1614
IMPL_LINK_NOARG(CustomAnimationDurationTabPage,DurationModifiedHdl,weld::MetricSpinButton &,void)1615 IMPL_LINK_NOARG(CustomAnimationDurationTabPage, DurationModifiedHdl, weld::MetricSpinButton&, void)
1616 {
1617 if (!mxCBXDuration->get_text().isEmpty())
1618 {
1619 double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE));
1620 if(duration_value <= 0.0)
1621 mxCBXDuration->set_value(1, FieldUnit::NONE);
1622 else
1623 mxCBXDuration->set_value(duration_value, FieldUnit::NONE);
1624 }
1625 }
1626
update(STLPropertySet * pSet)1627 void CustomAnimationDurationTabPage::update( STLPropertySet* pSet )
1628 {
1629 auto nPos = mxLBStart->get_active();
1630 if (nPos != -1)
1631 {
1632 sal_Int16 nStart;
1633 sal_Int16 nOldStart = -1;
1634
1635 switch( nPos )
1636 {
1637 case 1: nStart = EffectNodeType::WITH_PREVIOUS; break;
1638 case 2: nStart = EffectNodeType::AFTER_PREVIOUS; break;
1639 default:
1640 nStart = EffectNodeType::ON_CLICK; break;
1641 }
1642
1643 if(mpSet->getPropertyState( nHandleStart ) != STLPropertyState::Ambiguous)
1644 mpSet->getPropertyValue( nHandleStart ) >>= nOldStart;
1645
1646 if( nStart != nOldStart )
1647 pSet->setPropertyValue( nHandleStart, makeAny( nStart ) );
1648 }
1649
1650 {
1651 double fBegin = static_cast<double>(mxMFStartDelay->get_value(FieldUnit::NONE)) / 10.0;
1652 double fOldBegin = -1.0;
1653
1654 if( mpSet->getPropertyState( nHandleBegin ) != STLPropertyState::Ambiguous )
1655 mpSet->getPropertyValue( nHandleBegin ) >>= fOldBegin;
1656
1657 if( fBegin != fOldBegin )
1658 pSet->setPropertyValue( nHandleBegin, makeAny( fBegin ) );
1659 }
1660
1661 nPos = mxCBRepeat->get_active();
1662 if (nPos != -1 || !mxCBRepeat->get_active_text().isEmpty())
1663 {
1664 Any aRepeatCount;
1665 Any aEnd;
1666
1667 switch( nPos )
1668 {
1669 case 0:
1670 break;
1671
1672 case 6:
1673 {
1674 Event aEvent;
1675 aEvent.Trigger = EventTrigger::ON_NEXT;
1676 aEvent.Repeat = 0;
1677 aEnd <<= aEvent;
1678 }
1679 [[fallthrough]];
1680 case 7:
1681 aRepeatCount <<= Timing_INDEFINITE;
1682 break;
1683 default:
1684 {
1685 OUString aText(mxCBRepeat->get_text(nPos));
1686 if( !aText.isEmpty() )
1687 aRepeatCount <<= aText.toDouble();
1688 }
1689 }
1690
1691 Any aOldRepeatCount( aRepeatCount );
1692 if( mpSet->getPropertyState( nHandleRepeat ) != STLPropertyState::Ambiguous )
1693 aOldRepeatCount = mpSet->getPropertyValue( nHandleRepeat );
1694
1695 if( aRepeatCount != aOldRepeatCount )
1696 pSet->setPropertyValue( nHandleRepeat, aRepeatCount );
1697
1698 Any aOldEnd( aEnd );
1699 if( mpSet->getPropertyState( nHandleEnd ) != STLPropertyState::Ambiguous )
1700 aOldEnd = mpSet->getPropertyValue( nHandleEnd );
1701
1702 if( aEnd != aOldEnd )
1703 pSet->setPropertyValue( nHandleEnd, aEnd );
1704 }
1705
1706 double fDuration = -1.0;
1707
1708 if (!mxCBXDuration->get_text().isEmpty())
1709 {
1710 double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE));
1711
1712 if(duration_value > 0)
1713 fDuration = duration_value/100.0;
1714 }
1715
1716 if( fDuration != -1.0 )
1717 {
1718 double fOldDuration = -1;
1719
1720 if( mpSet->getPropertyState( nHandleDuration ) != STLPropertyState::Ambiguous )
1721 mpSet->getPropertyValue( nHandleDuration ) >>= fOldDuration;
1722
1723 if( fDuration != fOldDuration )
1724 pSet->setPropertyValue( nHandleDuration, makeAny( fDuration ) );
1725 }
1726
1727 if (mxCBXRewind->get_state() != TRISTATE_INDET)
1728 {
1729 sal_Int16 nFill = mxCBXRewind->get_active() ? AnimationFill::REMOVE : AnimationFill::HOLD;
1730
1731 bool bSet = true;
1732
1733 if( mpSet->getPropertyState( nHandleRewind ) != STLPropertyState::Ambiguous )
1734 {
1735 sal_Int16 nOldFill = 0;
1736 mpSet->getPropertyValue( nHandleRewind ) >>= nOldFill;
1737 bSet = nFill != nOldFill;
1738 }
1739
1740 if( bSet )
1741 pSet->setPropertyValue( nHandleRewind, makeAny( nFill ) );
1742 }
1743
1744 Reference< XShape > xTrigger;
1745
1746 if (mxRBInteractive->get_active())
1747 {
1748 nPos = mxLBTrigger->get_active();
1749 if (nPos != -1)
1750 {
1751 sal_Int32 nShape = mxLBTrigger->get_id(nPos).toInt32();
1752
1753 Reference< XDrawPage > xCurrentPage;
1754 mpSet->getPropertyValue( nHandleCurrentPage ) >>= xCurrentPage;
1755
1756 if( xCurrentPage.is() && (nShape >= 0) && (nShape < xCurrentPage->getCount()) )
1757 xCurrentPage->getByIndex( nShape ) >>= xTrigger;
1758 }
1759 }
1760
1761 if (xTrigger.is() || mxRBClickSequence->get_active())
1762 {
1763 Any aNewValue( makeAny( xTrigger ) );
1764 Any aOldValue;
1765
1766 if( mpSet->getPropertyState( nHandleTrigger ) != STLPropertyState::Ambiguous )
1767 aOldValue = mpSet->getPropertyValue( nHandleTrigger );
1768
1769 if( aNewValue != aOldValue )
1770 pSet->setPropertyValue( nHandleTrigger, aNewValue );
1771 }
1772 }
1773
1774 class CustomAnimationTextAnimTabPage
1775 {
1776 public:
1777 CustomAnimationTextAnimTabPage(weld::Container* pParent, const STLPropertySet* pSet);
1778
1779 void update( STLPropertySet* pSet );
1780
1781 void updateControlStates();
1782 DECL_LINK(implSelectHdl, weld::ComboBox&, void);
1783
1784 private:
1785 const STLPropertySet* mpSet;
1786 bool mbHasVisibleShapes;
1787
1788 std::unique_ptr<weld::Builder> mxBuilder;
1789 std::unique_ptr<weld::Container> mxContainer;
1790 std::unique_ptr<weld::Label> mxFTGroupText;
1791 std::unique_ptr<weld::ComboBox> mxLBGroupText;
1792 std::unique_ptr<weld::CheckButton> mxCBXGroupAuto;
1793 std::unique_ptr<weld::MetricSpinButton> mxMFGroupAuto;
1794 std::unique_ptr<weld::CheckButton> mxCBXAnimateForm;
1795 std::unique_ptr<weld::CheckButton> mxCBXReverse;
1796 };
1797
CustomAnimationTextAnimTabPage(weld::Container * pParent,const STLPropertySet * pSet)1798 CustomAnimationTextAnimTabPage::CustomAnimationTextAnimTabPage(weld::Container* pParent, const STLPropertySet* pSet)
1799 : mpSet(pSet)
1800 , mbHasVisibleShapes(true)
1801 , mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationtexttab.ui"))
1802 , mxContainer(mxBuilder->weld_container("TextAnimationTab"))
1803 , mxFTGroupText(mxBuilder->weld_label("group_text_label"))
1804 , mxLBGroupText(mxBuilder->weld_combo_box("group_text_list"))
1805 , mxCBXGroupAuto(mxBuilder->weld_check_button("auto_after"))
1806 , mxMFGroupAuto(mxBuilder->weld_metric_spin_button("auto_after_value",FieldUnit::SECOND))
1807 , mxCBXAnimateForm(mxBuilder->weld_check_button("animate_shape"))
1808 , mxCBXReverse(mxBuilder->weld_check_button("reverse_order"))
1809 {
1810 mxLBGroupText->connect_changed(LINK(this, CustomAnimationTextAnimTabPage, implSelectHdl));
1811
1812 if( pSet->getPropertyState( nHandleTextGrouping ) != STLPropertyState::Ambiguous )
1813 {
1814 sal_Int32 nTextGrouping = 0;
1815 if( pSet->getPropertyValue( nHandleTextGrouping ) >>= nTextGrouping )
1816 mxLBGroupText->set_active(nTextGrouping + 1);
1817 }
1818
1819 if( pSet->getPropertyState( nHandleHasVisibleShape ) != STLPropertyState::Ambiguous )
1820 pSet->getPropertyValue( nHandleHasVisibleShape ) >>= mbHasVisibleShapes;
1821
1822 if( pSet->getPropertyState( nHandleTextGroupingAuto ) != STLPropertyState::Ambiguous )
1823 {
1824 double fTextGroupingAuto = 0.0;
1825 if( pSet->getPropertyValue( nHandleTextGroupingAuto ) >>= fTextGroupingAuto )
1826 {
1827 mxCBXGroupAuto->set_active(fTextGroupingAuto >= 0.0);
1828 if( fTextGroupingAuto >= 0.0 )
1829 mxMFGroupAuto->set_value(static_cast<::tools::Long>(fTextGroupingAuto*10), FieldUnit::NONE);
1830 }
1831 }
1832 else
1833 {
1834 mxCBXGroupAuto->set_state( TRISTATE_INDET );
1835 }
1836
1837 mxCBXAnimateForm->set_state( TRISTATE_INDET );
1838 if( pSet->getPropertyState( nHandleAnimateForm ) != STLPropertyState::Ambiguous )
1839 {
1840 bool bAnimateForm = false;
1841 if( pSet->getPropertyValue( nHandleAnimateForm ) >>= bAnimateForm )
1842 {
1843 mxCBXAnimateForm->set_active( bAnimateForm );
1844 }
1845 }
1846 else
1847 {
1848 mxCBXAnimateForm->set_sensitive(false);
1849 }
1850
1851 mxCBXReverse->set_state(TRISTATE_INDET);
1852 if( pSet->getPropertyState( nHandleTextReverse ) != STLPropertyState::Ambiguous )
1853 {
1854 bool bTextReverse = false;
1855 if( pSet->getPropertyValue( nHandleTextReverse ) >>= bTextReverse )
1856 {
1857 mxCBXReverse->set_active( bTextReverse );
1858 }
1859 }
1860
1861 if( pSet->getPropertyState( nHandleMaxParaDepth ) == STLPropertyState::Direct )
1862 {
1863 sal_Int32 nMaxParaDepth = 0;
1864 pSet->getPropertyValue( nHandleMaxParaDepth ) >>= nMaxParaDepth;
1865 nMaxParaDepth += 1;
1866
1867 sal_Int32 nPos = 6;
1868 while( (nPos > 2) && (nPos > nMaxParaDepth) )
1869 {
1870 mxLBGroupText->remove(nPos);
1871 nPos--;
1872 }
1873 }
1874
1875 updateControlStates();
1876 }
1877
update(STLPropertySet * pSet)1878 void CustomAnimationTextAnimTabPage::update( STLPropertySet* pSet )
1879 {
1880 auto nPos = mxLBGroupText->get_active();
1881 if (nPos != -1)
1882 {
1883 sal_Int32 nTextGrouping = nPos - 1;
1884 sal_Int32 nOldGrouping = -2;
1885
1886 if(mpSet->getPropertyState( nHandleTextGrouping ) != STLPropertyState::Ambiguous)
1887 mpSet->getPropertyValue( nHandleTextGrouping ) >>= nOldGrouping;
1888
1889 if( nTextGrouping != nOldGrouping )
1890 pSet->setPropertyValue( nHandleTextGrouping, makeAny( nTextGrouping ) );
1891 }
1892
1893 if (nPos != 0)
1894 {
1895 bool bTextReverse = mxCBXReverse->get_active();
1896 bool bOldTextReverse = !bTextReverse;
1897
1898 if(mpSet->getPropertyState( nHandleTextReverse ) != STLPropertyState::Ambiguous)
1899 mpSet->getPropertyValue( nHandleTextReverse ) >>= bOldTextReverse;
1900
1901 if( bTextReverse != bOldTextReverse )
1902 pSet->setPropertyValue( nHandleTextReverse, makeAny( bTextReverse ) );
1903
1904 if( nPos > 1 )
1905 {
1906 double fTextGroupingAuto = mxCBXGroupAuto->get_active() ? mxMFGroupAuto->get_value(FieldUnit::NONE) / 10.0 : -1.0;
1907 double fOldTextGroupingAuto = -2.0;
1908
1909 if(mpSet->getPropertyState( nHandleTextGroupingAuto ) != STLPropertyState::Ambiguous)
1910 mpSet->getPropertyValue( nHandleTextGroupingAuto ) >>= fOldTextGroupingAuto;
1911
1912 if( fTextGroupingAuto != fOldTextGroupingAuto )
1913 pSet->setPropertyValue( nHandleTextGroupingAuto, makeAny( fTextGroupingAuto ) );
1914 }
1915 }
1916 //#i120049# impress crashes when modifying the "Random effects" animation
1917 //effect's trigger condition to "Start effect on click of".
1918 //If this control is disabled, we should ignore its value
1919 if (mxCBXAnimateForm->get_sensitive())
1920 {
1921 bool bAnimateForm = mxCBXAnimateForm->get_active();
1922 bool bOldAnimateForm = !bAnimateForm;
1923
1924 if(mpSet->getPropertyState( nHandleAnimateForm ) != STLPropertyState::Ambiguous)
1925 mpSet->getPropertyValue( nHandleAnimateForm ) >>= bOldAnimateForm;
1926
1927 if( bAnimateForm != bOldAnimateForm )
1928 pSet->setPropertyValue( nHandleAnimateForm, makeAny( bAnimateForm ) );
1929 }
1930 }
1931
updateControlStates()1932 void CustomAnimationTextAnimTabPage::updateControlStates()
1933 {
1934 auto nPos = mxLBGroupText->get_active();
1935
1936 mxCBXGroupAuto->set_sensitive( nPos > 1 );
1937 mxMFGroupAuto->set_sensitive( nPos > 1 );
1938 mxCBXReverse->set_sensitive( nPos > 0 );
1939
1940 if( !mbHasVisibleShapes && nPos > 0 )
1941 {
1942 mxCBXAnimateForm->set_active(false);
1943 mxCBXAnimateForm->set_sensitive(false);
1944 }
1945 else
1946 {
1947 mxCBXAnimateForm->set_sensitive(true);
1948 }
1949 }
1950
IMPL_LINK_NOARG(CustomAnimationTextAnimTabPage,implSelectHdl,weld::ComboBox &,void)1951 IMPL_LINK_NOARG(CustomAnimationTextAnimTabPage, implSelectHdl, weld::ComboBox&, void)
1952 {
1953 updateControlStates();
1954 }
1955
CustomAnimationDialog(weld::Window * pParent,std::unique_ptr<STLPropertySet> pSet,const OString & rPage)1956 CustomAnimationDialog::CustomAnimationDialog(weld::Window* pParent, std::unique_ptr<STLPropertySet> pSet, const OString& rPage)
1957 : GenericDialogController(pParent, "modules/simpress/ui/customanimationproperties.ui", "CustomAnimationProperties")
1958 , mxSet(std::move(pSet))
1959 , mxTabControl(m_xBuilder->weld_notebook("tabcontrol"))
1960 , mxDurationTabPage(new CustomAnimationDurationTabPage(mxTabControl->get_page("timing"), mxSet.get()))
1961 , mxEffectTabPage(new CustomAnimationEffectTabPage(mxTabControl->get_page("effect"), m_xDialog.get(), mxSet.get()))
1962 {
1963 bool bHasText = false;
1964 if( mxSet->getPropertyState( nHandleHasText ) != STLPropertyState::Ambiguous )
1965 mxSet->getPropertyValue( nHandleHasText ) >>= bHasText;
1966
1967 if( bHasText )
1968 {
1969 mxTextAnimTabPage.reset(new CustomAnimationTextAnimTabPage(mxTabControl->get_page("textanim"), mxSet.get()));
1970 }
1971 else
1972 {
1973 mxTabControl->remove_page("textanim");
1974 }
1975
1976 if (!rPage.isEmpty())
1977 mxTabControl->set_current_page(rPage);
1978 }
1979
~CustomAnimationDialog()1980 CustomAnimationDialog::~CustomAnimationDialog()
1981 {
1982 }
1983
getResultSet()1984 STLPropertySet* CustomAnimationDialog::getResultSet()
1985 {
1986 mxResultSet = createDefaultSet();
1987
1988 mxEffectTabPage->update( mxResultSet.get() );
1989 mxDurationTabPage->update( mxResultSet.get() );
1990 if (mxTextAnimTabPage)
1991 mxTextAnimTabPage->update( mxResultSet.get() );
1992
1993 return mxResultSet.get();
1994 }
1995
createDefaultSet()1996 std::unique_ptr<STLPropertySet> CustomAnimationDialog::createDefaultSet()
1997 {
1998 Any aEmpty;
1999
2000 std::unique_ptr<STLPropertySet> pSet(new STLPropertySet());
2001 pSet->setPropertyDefaultValue( nHandleMaxParaDepth, makeAny( sal_Int32(-1) ) );
2002
2003 pSet->setPropertyDefaultValue( nHandleHasAfterEffect, makeAny( false ) );
2004 pSet->setPropertyDefaultValue( nHandleAfterEffectOnNextEffect, makeAny( false ) );
2005 pSet->setPropertyDefaultValue( nHandleDimColor, aEmpty );
2006 pSet->setPropertyDefaultValue( nHandleIterateType, makeAny( sal_Int16(0) ) );
2007 pSet->setPropertyDefaultValue( nHandleIterateInterval, makeAny( 0.0 ) );
2008
2009 pSet->setPropertyDefaultValue( nHandleStart, makeAny( sal_Int16(EffectNodeType::ON_CLICK) ) );
2010 pSet->setPropertyDefaultValue( nHandleBegin, makeAny( 0.0 ) );
2011 pSet->setPropertyDefaultValue( nHandleDuration, makeAny( 2.0 ) );
2012 pSet->setPropertyDefaultValue( nHandleRepeat, aEmpty );
2013 pSet->setPropertyDefaultValue( nHandleRewind, makeAny( AnimationFill::HOLD ) );
2014
2015 pSet->setPropertyDefaultValue( nHandleEnd, aEmpty );
2016
2017 pSet->setPropertyDefaultValue( nHandlePresetId, aEmpty );
2018 pSet->setPropertyDefaultValue( nHandleProperty1Type, makeAny( nPropertyTypeNone ) );
2019 pSet->setPropertyDefaultValue( nHandleProperty1Value, aEmpty );
2020 pSet->setPropertyDefaultValue( nHandleProperty2Type, makeAny( nPropertyTypeNone ) );
2021 pSet->setPropertyDefaultValue( nHandleProperty2Value, aEmpty );
2022 pSet->setPropertyDefaultValue( nHandleAccelerate, aEmpty );
2023 pSet->setPropertyDefaultValue( nHandleDecelerate, aEmpty );
2024 pSet->setPropertyDefaultValue( nHandleAutoReverse, aEmpty );
2025 pSet->setPropertyDefaultValue( nHandleTrigger, aEmpty );
2026
2027 pSet->setPropertyDefaultValue( nHandleHasText, makeAny( false ) );
2028 pSet->setPropertyDefaultValue( nHandleHasVisibleShape, makeAny( false ) );
2029 pSet->setPropertyDefaultValue( nHandleTextGrouping, makeAny( sal_Int32(-1) ) );
2030 pSet->setPropertyDefaultValue( nHandleAnimateForm, makeAny( true ) );
2031 pSet->setPropertyDefaultValue( nHandleTextGroupingAuto, makeAny( -1.0 ) );
2032 pSet->setPropertyDefaultValue( nHandleTextReverse, makeAny( false ) );
2033
2034 pSet->setPropertyDefaultValue( nHandleCurrentPage, aEmpty );
2035
2036 pSet->setPropertyDefaultValue( nHandleSoundURL, aEmpty );
2037 pSet->setPropertyDefaultValue( nHandleSoundVolume, makeAny( 1.0) );
2038 pSet->setPropertyDefaultValue( nHandleSoundEndAfterSlide, makeAny( sal_Int32(0) ) );
2039
2040 pSet->setPropertyDefaultValue( nHandleCommand, makeAny( sal_Int16(0) ) );
2041 return pSet;
2042 }
2043
create(sal_Int32 nType,weld::Label * pLabel,weld::Container * pParent,weld::Window * pTopLevel,const Any & rValue,const OUString & rPresetId,const Link<LinkParamNone *,void> & rModifyHdl)2044 std::unique_ptr<SdPropertySubControl> SdPropertySubControl::create(sal_Int32 nType, weld::Label* pLabel, weld::Container* pParent, weld::Window* pTopLevel, const Any& rValue, const OUString& rPresetId, const Link<LinkParamNone*,void>& rModifyHdl)
2045 {
2046 std::unique_ptr<SdPropertySubControl> pSubControl;
2047 switch( nType )
2048 {
2049 case nPropertyTypeDirection:
2050 case nPropertyTypeSpokes:
2051 case nPropertyTypeZoom:
2052 pSubControl.reset( new SdPresetPropertyBox( pLabel, pParent, rValue, rPresetId, rModifyHdl ) );
2053 break;
2054
2055 case nPropertyTypeColor:
2056 case nPropertyTypeFillColor:
2057 case nPropertyTypeFirstColor:
2058 case nPropertyTypeCharColor:
2059 case nPropertyTypeLineColor:
2060 pSubControl.reset( new SdColorPropertyBox( pLabel, pParent, pTopLevel, rValue, rModifyHdl ) );
2061 break;
2062
2063 case nPropertyTypeFont:
2064 pSubControl.reset( new SdFontPropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2065 break;
2066
2067 case nPropertyTypeCharHeight:
2068 pSubControl.reset( new SdCharHeightPropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2069 break;
2070
2071 case nPropertyTypeRotate:
2072 pSubControl.reset( new SdRotationPropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2073 break;
2074
2075 case nPropertyTypeTransparency:
2076 pSubControl.reset( new SdTransparencyPropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2077 break;
2078
2079 case nPropertyTypeScale:
2080 pSubControl.reset( new SdScalePropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2081 break;
2082
2083 case nPropertyTypeCharDecoration:
2084 pSubControl.reset( new SdFontStylePropertyBox( pLabel, pParent, rValue, rModifyHdl ) );
2085 break;
2086 }
2087
2088 return pSubControl;
2089 }
2090
2091 }
2092
2093 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2094