Line data Source code
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 :
21 : #include <com/sun/star/presentation/EffectPresetClass.hpp>
22 : #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
23 : #include <com/sun/star/animations/ParallelTimeContainer.hpp>
24 : #include <com/sun/star/view/XSelectionSupplier.hpp>
25 : #include <com/sun/star/drawing/XDrawView.hpp>
26 : #include <com/sun/star/drawing/XShape.hpp>
27 : #include <com/sun/star/beans/XPropertySet.hpp>
28 : #include <com/sun/star/presentation/EffectNodeType.hpp>
29 : #include <com/sun/star/presentation/EffectCommands.hpp>
30 : #include <com/sun/star/animations/AnimationTransformType.hpp>
31 : #include <com/sun/star/text/XTextRangeCompare.hpp>
32 : #include <com/sun/star/container/XEnumerationAccess.hpp>
33 : #include <com/sun/star/container/XIndexAccess.hpp>
34 : #include <com/sun/star/presentation/ParagraphTarget.hpp>
35 : #include <com/sun/star/text/XText.hpp>
36 : #include <com/sun/star/awt/XWindow.hpp>
37 : #include <com/sun/star/drawing/LineStyle.hpp>
38 : #include <com/sun/star/drawing/FillStyle.hpp>
39 : #include <comphelper/processfactory.hxx>
40 : #include <sfx2/dispatch.hxx>
41 : #include "STLPropertySet.hxx"
42 : #include "CustomAnimationPane.hxx"
43 : #include "CustomAnimationDialog.hxx"
44 : #include "CustomAnimationCreateDialog.hxx"
45 : #include "CustomAnimationPane.hrc"
46 : #include "CustomAnimation.hrc"
47 : #include "CustomAnimationList.hxx"
48 : #include <vcl/lstbox.hxx>
49 : #include <vcl/fixed.hxx>
50 :
51 : #include <vcl/button.hxx>
52 : #include <vcl/combobox.hxx>
53 : #include <vcl/scrbar.hxx>
54 :
55 : #include <comphelper/sequence.hxx>
56 : #include <sfx2/frame.hxx>
57 : #include <sfx2/sidebar/Theme.hxx>
58 :
59 : #include <svx/unoapi.hxx>
60 : #include <svx/svxids.hrc>
61 : #include <DrawDocShell.hxx>
62 : #include <ViewShellBase.hxx>
63 : #include "DrawViewShell.hxx"
64 : #include "DrawController.hxx"
65 : #include "sdresid.hxx"
66 : #include "drawview.hxx"
67 : #include "slideshow.hxx"
68 : #include "undoanim.hxx"
69 : #include "optsitem.hxx"
70 : #include "sddll.hxx"
71 : #include "framework/FrameworkHelper.hxx"
72 :
73 : #include "EventMultiplexer.hxx"
74 : #include "DialogListBox.hxx"
75 :
76 : #include "glob.hrc"
77 : #include "sdpage.hxx"
78 : #include "drawdoc.hxx"
79 : #include "app.hrc"
80 :
81 : #include <memory>
82 : #include <algorithm>
83 :
84 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
85 : #include <basegfx/matrix/b2dhommatrix.hxx>
86 : #include <basegfx/range/b2drange.hxx>
87 :
88 : using namespace ::com::sun::star;
89 : using namespace ::com::sun::star::animations;
90 : using namespace ::com::sun::star::presentation;
91 : using namespace ::com::sun::star::text;
92 :
93 : using namespace ::com::sun::star::uno;
94 : using namespace ::com::sun::star::drawing;
95 : using ::com::sun::star::view::XSelectionSupplier;
96 : using ::com::sun::star::view::XSelectionChangeListener;
97 : using ::com::sun::star::frame::XController;
98 : using ::com::sun::star::frame::XModel;
99 : using ::com::sun::star::beans::XPropertySet;
100 : using ::com::sun::star::beans::XPropertyChangeListener;
101 : using ::com::sun::star::container::XIndexAccess;
102 : using ::com::sun::star::container::XEnumerationAccess;
103 : using ::com::sun::star::container::XEnumeration;
104 : using ::com::sun::star::text::XText;
105 : using ::sd::framework::FrameworkHelper;
106 :
107 : namespace sd {
108 :
109 : // --------------------------------------------------------------------
110 :
111 0 : void fillDurationComboBox( ComboBox* pBox )
112 : {
113 : static const double gdVerySlow = 5.0;
114 : static const double gdSlow = 3.0;
115 : static const double gdNormal = 2.0;
116 : static const double gdFast = 1.0;
117 : static const double gdVeryFast = 0.5;
118 :
119 0 : String aVerySlow( SdResId( STR_CUSTOMANIMATION_DURATION_VERY_SLOW ) );
120 0 : pBox->SetEntryData( pBox->InsertEntry( aVerySlow ), (void*)&gdVerySlow );
121 :
122 0 : String aSlow( SdResId( STR_CUSTOMANIMATION_DURATION_SLOW ) );
123 0 : pBox->SetEntryData( pBox->InsertEntry( aSlow ), (void*)&gdSlow );
124 :
125 0 : String aNormal( SdResId( STR_CUSTOMANIMATION_DURATION_NORMAL ) );
126 0 : pBox->SetEntryData( pBox->InsertEntry( aNormal ), (void*)&gdNormal );
127 :
128 0 : String aFast( SdResId( STR_CUSTOMANIMATION_DURATION_FAST ) );
129 0 : pBox->SetEntryData( pBox->InsertEntry( aFast ), (void*)&gdFast );
130 :
131 0 : String aVeryFast( SdResId( STR_CUSTOMANIMATION_DURATION_VERY_FAST ) );
132 0 : pBox->SetEntryData( pBox->InsertEntry( aVeryFast ), (void*)&gdVeryFast );
133 0 : }
134 :
135 0 : void fillRepeatComboBox( ComboBox* pBox )
136 : {
137 0 : String aNone( SdResId( STR_CUSTOMANIMATION_REPEAT_NONE ) );
138 0 : pBox->SetEntryData( pBox->InsertEntry( aNone ), (void*)((sal_Int32)0) );
139 :
140 0 : pBox->SetEntryData( pBox->InsertEntry( OUString::number( 2 ) ), (void*)((sal_Int32)1) );
141 0 : pBox->SetEntryData( pBox->InsertEntry( OUString::number( 3 ) ), (void*)((sal_Int32)3) );
142 0 : pBox->SetEntryData( pBox->InsertEntry( OUString::number( 4 ) ), (void*)((sal_Int32)4) );
143 0 : pBox->SetEntryData( pBox->InsertEntry( OUString::number( 5 ) ), (void*)((sal_Int32)5) );
144 0 : pBox->SetEntryData( pBox->InsertEntry( OUString::number( 10 ) ), (void*)((sal_Int32)10) );
145 :
146 0 : String aUntilClick( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_NEXT_CLICK ) );
147 0 : pBox->SetEntryData( pBox->InsertEntry( aUntilClick ), (void*)((sal_Int32)-1) );
148 :
149 0 : String aEndOfSlide( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_END_OF_SLIDE ) );
150 0 : pBox->SetEntryData( pBox->InsertEntry( aEndOfSlide ), (void*)((sal_Int32)-2) );
151 0 : }
152 :
153 : // --------------------------------------------------------------------
154 :
155 0 : CustomAnimationPane::CustomAnimationPane( ::Window* pParent, ViewShellBase& rBase, const Size& rMinSize )
156 : : Control( pParent, SdResId(DLG_CUSTOMANIMATIONPANE) ),
157 : mrBase( rBase ),
158 : mpCustomAnimationPresets(NULL),
159 : mnPropertyType( nPropertyTypeNone ),
160 : maMinSize( rMinSize ),
161 0 : mxModel( rBase.GetDocShell()->GetDoc()->getUnoModel(), UNO_QUERY ),
162 0 : maLateInitTimer()
163 : {
164 : // load resources
165 0 : mpFLEffect = new FixedLine( this, SdResId( FL_EFFECT ) );
166 :
167 0 : mpPBAddEffect = new PushButton( this, SdResId( PB_ADD_EFFECT ) );
168 0 : mpPBChangeEffect = new PushButton( this, SdResId( PB_CHANGE_EFFECT ) );
169 0 : mpPBRemoveEffect = new PushButton( this, SdResId( PB_REMOVE_EFFECT ) );
170 :
171 0 : mpFLModify = new FixedLine( this, SdResId( FL_MODIFY ) );
172 :
173 0 : mpFTStart = new FixedText( this, SdResId( FT_START ) );
174 0 : mpLBStart = new ListBox( this, SdResId( LB_START ) );
175 0 : mpFTProperty = new FixedText( this, SdResId( FT_PROPERTY ) );
176 0 : mpLBProperty = new PropertyControl( this, SdResId( LB_PROPERTY ) );
177 0 : mpPBPropertyMore = new PushButton( this, SdResId( PB_PROPERTY_MORE ) );
178 :
179 0 : mpFTSpeed = new FixedText( this, SdResId( FT_SPEED ) );
180 0 : mpCBSpeed = new ComboBox( this, SdResId( CB_SPEED ) );
181 :
182 0 : mpCustomAnimationList = new CustomAnimationList( this, SdResId( CT_CUSTOM_ANIMATION_LIST ), this );
183 :
184 0 : mpPBMoveUp = new PushButton( this, SdResId( PB_MOVE_UP ) );
185 0 : mpPBMoveDown = new PushButton( this, SdResId( PB_MOVE_DOWN ) );
186 0 : mpFTChangeOrder = new FixedText( this, SdResId( FT_CHANGE_ORDER ) );
187 0 : mpFLSeparator1 = new FixedLine( this, SdResId( FL_SEPARATOR1 ) );
188 0 : mpPBPlay = new PushButton( this, SdResId( PB_PLAY ) );
189 0 : mpPBSlideShow = new PushButton( this, SdResId( PB_SLIDE_SHOW ) );
190 0 : mpFLSeparator2 = new FixedLine( this, SdResId( FL_SEPARATOR2 ) );
191 0 : mpCBAutoPreview = new CheckBox( this, SdResId( CB_AUTOPREVIEW ) );
192 :
193 0 : maStrProperty = mpFTProperty->GetText();
194 :
195 0 : FreeResource();
196 :
197 : // use bold font for group headings (same font for all fixed lines):
198 0 : Font font( mpFLEffect->GetFont() );
199 0 : font.SetWeight( WEIGHT_BOLD );
200 0 : mpFLEffect->SetFont( font );
201 0 : mpFLModify->SetFont( font );
202 :
203 0 : fillDurationComboBox( mpCBSpeed );
204 0 : mpPBMoveUp->SetSymbol( SYMBOL_ARROW_UP );
205 0 : mpPBMoveDown->SetSymbol( SYMBOL_ARROW_DOWN );
206 :
207 0 : mpPBAddEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
208 0 : mpPBChangeEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
209 0 : mpPBRemoveEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
210 0 : mpLBStart->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
211 0 : mpCBSpeed->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
212 0 : mpPBPropertyMore->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
213 0 : mpPBMoveUp->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
214 0 : mpPBMoveDown->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
215 0 : mpPBPlay->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
216 0 : mpPBSlideShow->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
217 0 : mpCBAutoPreview->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
218 :
219 0 : maStrModify = mpFLEffect->GetText();
220 :
221 : // resize controls according to current size
222 0 : updateLayout();
223 :
224 : // get current controller and initialize listeners
225 : try
226 : {
227 0 : mxView = Reference< XDrawView >::query(mrBase.GetController());
228 0 : addListener();
229 : }
230 0 : catch( Exception& )
231 : {
232 : OSL_FAIL( "sd::CustomAnimationPane::CustomAnimationPane(), Exception caught!" );
233 : }
234 :
235 : // get current page and update custom animation list
236 0 : onChangeCurrentPage();
237 :
238 : // Wait a short time before the presets list is created. This gives the
239 : // system time to paint the control.
240 0 : maLateInitTimer.SetTimeout(100);
241 0 : maLateInitTimer.SetTimeoutHdl(LINK(this, CustomAnimationPane, lateInitCallback));
242 0 : maLateInitTimer.Start();
243 :
244 0 : UpdateLook();
245 0 : }
246 :
247 0 : CustomAnimationPane::~CustomAnimationPane()
248 : {
249 0 : maLateInitTimer.Stop();
250 :
251 0 : removeListener();
252 :
253 0 : MotionPathTagVector aTags;
254 0 : aTags.swap( maMotionPathTags );
255 0 : MotionPathTagVector::iterator aIter;
256 0 : for( aIter = aTags.begin(); aIter != aTags.end(); ++aIter )
257 0 : (*aIter)->Dispose();
258 :
259 0 : delete mpFLModify;
260 0 : delete mpPBAddEffect;
261 0 : delete mpPBChangeEffect;
262 0 : delete mpPBRemoveEffect;
263 0 : delete mpFLEffect;
264 0 : delete mpFTStart;
265 0 : delete mpLBStart;
266 0 : delete mpFTProperty;
267 0 : delete mpLBProperty;
268 0 : delete mpPBPropertyMore;
269 0 : delete mpFTSpeed;
270 0 : delete mpCBSpeed;
271 0 : delete mpCustomAnimationList;
272 0 : delete mpFTChangeOrder;
273 0 : delete mpPBMoveUp;
274 0 : delete mpPBMoveDown;
275 0 : delete mpFLSeparator1;
276 0 : delete mpPBPlay;
277 0 : delete mpPBSlideShow;
278 0 : delete mpFLSeparator2;
279 0 : delete mpCBAutoPreview;
280 0 : }
281 :
282 0 : void CustomAnimationPane::addUndo()
283 : {
284 0 : ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
285 0 : if( pManager )
286 : {
287 0 : SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
288 0 : if( pPage )
289 0 : pManager->AddUndoAction( new UndoAnimation( mrBase.GetDocShell()->GetDoc(), pPage ) );
290 : }
291 0 : }
292 :
293 0 : void CustomAnimationPane::Resize()
294 : {
295 0 : updateLayout();
296 0 : }
297 :
298 0 : void CustomAnimationPane::StateChanged( StateChangedType nStateChange )
299 : {
300 0 : Control::StateChanged( nStateChange );
301 :
302 0 : if( nStateChange == STATE_CHANGE_VISIBLE )
303 0 : updateMotionPathTags();
304 0 : }
305 :
306 0 : void CustomAnimationPane::KeyInput( const KeyEvent& rKEvt )
307 : {
308 0 : if( mpCustomAnimationList )
309 0 : mpCustomAnimationList->KeyInput( rKEvt );
310 0 : }
311 :
312 0 : void CustomAnimationPane::addListener()
313 : {
314 0 : Link aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
315 : mrBase.GetEventMultiplexer()->AddEventListener (
316 : aLink,
317 : tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
318 : | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
319 : | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
320 : | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
321 : | tools::EventMultiplexerEvent::EID_DISPOSING
322 0 : | tools::EventMultiplexerEvent::EID_END_TEXT_EDIT);
323 0 : }
324 :
325 0 : void CustomAnimationPane::removeListener()
326 : {
327 0 : Link aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
328 0 : mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
329 0 : }
330 :
331 0 : IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,
332 : tools::EventMultiplexerEvent*,pEvent)
333 : {
334 0 : switch (pEvent->meEventId)
335 : {
336 : case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
337 0 : onSelectionChanged();
338 0 : break;
339 :
340 : case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
341 0 : onChangeCurrentPage();
342 0 : break;
343 :
344 : case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
345 : // At this moment the controller may not yet been set at model
346 : // or ViewShellBase. Take it from the view shell passed with
347 : // the event.
348 0 : if (mrBase.GetMainViewShell() != 0)
349 : {
350 0 : if( mrBase.GetMainViewShell()->GetShellType() == ViewShell::ST_IMPRESS )
351 : {
352 0 : mxView = Reference<XDrawView>::query(mrBase.GetDrawController());
353 0 : onSelectionChanged();
354 0 : onChangeCurrentPage();
355 0 : break;
356 : }
357 : }
358 : // fall through intended
359 : case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
360 0 : mxView = 0;
361 0 : mxCurrentPage = 0;
362 0 : updateControls();
363 0 : break;
364 :
365 : case tools::EventMultiplexerEvent::EID_DISPOSING:
366 0 : mxView.clear();
367 0 : onSelectionChanged();
368 0 : onChangeCurrentPage();
369 0 : break;
370 : case tools::EventMultiplexerEvent::EID_END_TEXT_EDIT:
371 0 : if( mpMainSequence.get() && pEvent->mpUserData )
372 0 : mpCustomAnimationList->update( mpMainSequence );
373 0 : break;
374 : }
375 0 : return 0;
376 : }
377 :
378 :
379 0 : void CustomAnimationPane::updateLayout()
380 : {
381 0 : Size aPaneSize( GetSizePixel() );
382 0 : if( aPaneSize.Width() < maMinSize.Width() )
383 0 : aPaneSize.Width() = maMinSize.Width();
384 :
385 0 : if( aPaneSize.Height() < maMinSize.Height() )
386 0 : aPaneSize.Height() = maMinSize.Height();
387 :
388 0 : Point aOffset( LogicToPixel( Point(3,3), MAP_APPFONT ) );
389 0 : Point aCursor( aOffset );
390 :
391 : // place the modify fixed line
392 :
393 : // place the "modify effect" fixed line
394 0 : Size aSize( mpFLModify->GetSizePixel() );
395 0 : aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
396 :
397 0 : mpFLModify->SetPosSizePixel( aCursor, aSize );
398 :
399 0 : aCursor.Y() += aSize.Height() + aOffset.Y();
400 :
401 0 : const int nButtonExtraWidth = 4 * aOffset.X();
402 :
403 : // the "add effect" button is placed top-left
404 0 : Size aCtrlSize( mpPBAddEffect->GetSizePixel() );
405 0 : aCtrlSize.setWidth( mpPBAddEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
406 0 : mpPBAddEffect->SetPosSizePixel( aCursor, aCtrlSize );
407 :
408 0 : aCursor.X() += aOffset.X() + aCtrlSize.Width();
409 :
410 : // place the "change effect" button
411 :
412 : // if the "change" button does not fit right of the "add effect", put it on the next line
413 0 : aCtrlSize = mpPBChangeEffect->GetSizePixel();
414 0 : aCtrlSize.setWidth( mpPBChangeEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
415 0 : if( ( aCursor.X() + aCtrlSize.Width() + aOffset.X() ) > aPaneSize.Width() )
416 : {
417 0 : aCursor.X() = aOffset.X();
418 0 : aCursor.Y() += aCtrlSize.Height() + aOffset.Y();
419 : }
420 0 : mpPBChangeEffect->SetPosSizePixel( aCursor, aCtrlSize );
421 :
422 0 : aCursor.X() += aOffset.X() + aCtrlSize.Width();
423 :
424 : // place the "remove effect" button
425 :
426 : // if the "remove" button does not fit right of the "add effect", put it on the next line
427 0 : aCtrlSize = mpPBRemoveEffect->GetSizePixel();
428 0 : aCtrlSize.setWidth( mpPBRemoveEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
429 0 : if( ( aCursor.X() + aCtrlSize.Width() + aOffset.X() ) > aPaneSize.Width() )
430 : {
431 0 : aCursor.X() = aOffset.X();
432 0 : aCursor.Y() += aCtrlSize.Height() + aOffset.Y();
433 : }
434 :
435 0 : mpPBRemoveEffect->SetPosSizePixel( aCursor, aCtrlSize );
436 :
437 0 : aCursor.X() = aOffset.X();
438 0 : aCursor.Y() += aCtrlSize.Height() + 2 * aOffset.Y();
439 :
440 : // place the "modify effect" fixed line
441 0 : aSize = mpFLEffect->GetSizePixel();
442 0 : aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
443 :
444 0 : mpFLEffect->SetPosSizePixel( aCursor, aSize );
445 :
446 0 : aCursor.Y() += aSize.Height() + aOffset.Y();
447 :
448 : // ---------------------------------------------------------------------------
449 : // place the properties controls
450 :
451 : // calc minimum width for fixedtext
452 :
453 0 : Size aFixedTextSize( mpFTStart->CalcMinimumSize() );
454 0 : long nWidth = aFixedTextSize.Width();
455 0 : aFixedTextSize = mpFTProperty->CalcMinimumSize();
456 0 : nWidth = std::max( nWidth, aFixedTextSize.Width() );
457 0 : aFixedTextSize = mpFTSpeed->CalcMinimumSize();
458 0 : aFixedTextSize.Width() = std::max( nWidth, aFixedTextSize.Width() ) + aOffset.X();
459 0 : mpFTStart->SetSizePixel(aFixedTextSize);
460 0 : mpFTProperty->SetSizePixel(aFixedTextSize);
461 0 : mpFTSpeed->SetSizePixel(aFixedTextSize);
462 :
463 0 : aSize = mpPBPropertyMore->GetSizePixel();
464 :
465 : // place the "start" fixed text
466 :
467 0 : Point aFTPos( aCursor );
468 0 : Point aLBPos( aCursor );
469 0 : Size aListBoxSize( LogicToPixel( Size( 60, 12 ), MAP_APPFONT ) );
470 0 : long nDeltaY = aListBoxSize.Height() + aOffset.Y();
471 :
472 : // linebreak?
473 0 : if( (aFixedTextSize.Width() + aListBoxSize.Width() + aSize.Width() + 4 * aOffset.X()) > aPaneSize.Width() )
474 : {
475 : // y position for list box is below fixed text
476 0 : aLBPos.Y() += aFixedTextSize.Height() + aOffset.Y();
477 :
478 : // height of fixed text + list box + something = 2 * list box
479 0 : nDeltaY = aListBoxSize.Height() + aFixedTextSize.Height() + 2*aOffset.Y();
480 : }
481 : else
482 : {
483 : // x position for list box is right of fixed text
484 0 : aLBPos.X() += aFixedTextSize.Width() + aOffset.X();
485 :
486 0 : if( aListBoxSize.Height() > aFixedTextSize.Height() )
487 0 : aFTPos.Y() = aLBPos.Y() + ((aListBoxSize.Height() - aFixedTextSize.Height()) >> 1);
488 : else
489 0 : aLBPos.Y() = aFTPos.Y() + ((aFixedTextSize.Height() - aListBoxSize.Height()) >> 1);
490 : }
491 :
492 : // width of the listbox is from its left side until end of pane
493 0 : aListBoxSize.Width() = aPaneSize.Width() - aLBPos.X() - aSize.Width() - 2 * aOffset.X();
494 :
495 0 : mpFTStart->SetPosPixel( aFTPos );
496 0 : mpLBStart->SetPosSizePixel( aLBPos, aListBoxSize );
497 :
498 0 : aFTPos.Y() += nDeltaY; aLBPos.Y() += nDeltaY;
499 :
500 0 : mpFTProperty->SetPosPixel( aFTPos );
501 0 : mpLBProperty->SetPosSizePixel( aLBPos, aListBoxSize );
502 0 : mpLBProperty->Resize();
503 :
504 0 : Point aMorePos( aLBPos );
505 0 : aMorePos.X() += aListBoxSize.Width() + aOffset.X();
506 0 : mpPBPropertyMore->SetPosPixel( aMorePos );
507 :
508 0 : aFTPos.Y() += nDeltaY; aLBPos.Y() += nDeltaY;
509 :
510 0 : mpFTSpeed->SetPosPixel( aFTPos );
511 0 : mpCBSpeed->SetPosSizePixel( aLBPos, aListBoxSize );
512 :
513 0 : aFTPos.Y() += nDeltaY + aOffset.Y();
514 :
515 0 : Point aListPos( aFTPos );
516 :
517 : // positionate the buttons on the bottom
518 :
519 : // place the auto preview checkbox
520 0 : aCursor = Point( aOffset.X(), aPaneSize.Height() - mpCBAutoPreview->GetSizePixel().Height() - aOffset.Y() );
521 0 : mpCBAutoPreview->SetPosPixel( aCursor );
522 :
523 : // place the separator 2 fixed line
524 0 : aCursor.Y() -= /* aOffset.Y() + */ mpFLSeparator2->GetSizePixel().Height();
525 0 : aSize = mpFLSeparator2->GetSizePixel();
526 0 : aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
527 0 : mpFLSeparator2->SetPosSizePixel( aCursor, aSize );
528 :
529 : // next, layout and place the play and slide show buttons
530 0 : aCtrlSize = mpPBSlideShow->GetSizePixel();
531 0 : aCtrlSize.setWidth( mpPBSlideShow->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
532 :
533 0 : Size aPlaySize( mpPBPlay->GetSizePixel() );
534 0 : aPlaySize.setWidth( mpPBPlay->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
535 :
536 0 : aCursor.Y() -= aCtrlSize.Height() /* + aOffset.Y() */;
537 :
538 : // do we need two lines for the buttons?
539 0 : int aTestWidth = aCursor.X() + mpPBPlay->GetSizePixel().Width() + 2 * aOffset.X() + mpPBSlideShow->GetSizePixel().Width();
540 0 : if( aTestWidth > aPaneSize.Width() )
541 : {
542 0 : mpPBSlideShow->SetPosSizePixel( aCursor, aCtrlSize );
543 0 : aCursor.Y() -= aCtrlSize.Height() + aOffset.Y();
544 0 : mpPBPlay->SetPosSizePixel( aCursor, aPlaySize );
545 : }
546 : else
547 : {
548 0 : mpPBPlay->SetPosSizePixel( aCursor, aPlaySize );
549 0 : aCursor.X() += aPlaySize.Width() + aOffset.X();
550 0 : mpPBSlideShow->SetPosSizePixel( aCursor, aCtrlSize );
551 : }
552 :
553 : // place the separator 1 fixed line
554 0 : aCursor.X() = aOffset.X();
555 0 : aCursor.Y() -= /* aOffset.Y() + */ mpFLSeparator1->GetSizePixel().Height();
556 0 : aSize = mpFLSeparator1->GetSizePixel();
557 0 : aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
558 0 : mpFLSeparator1->SetPosSizePixel( aCursor, aSize );
559 :
560 : // place the move down button
561 0 : aSize = mpPBMoveDown->GetSizePixel();
562 :
563 0 : aCursor.X() = aPaneSize.Width() - aOffset.X() - aSize.Width();
564 0 : aCursor.Y() -= aOffset.Y() + aSize.Height();
565 0 : mpPBMoveDown->SetPosPixel( aCursor );
566 :
567 0 : aCursor.X() -= aOffset.X() + aSize.Width();
568 0 : mpPBMoveUp->SetPosPixel( aCursor );
569 :
570 : // Place the change order label.
571 : // Its width has to be calculated dynamically so that is can be
572 : // displayed flush right without having too much space to the buttons
573 : // with some languages or truncated text with others.
574 0 : mpFTChangeOrder->SetSizePixel(mpFTChangeOrder->CalcMinimumSize());
575 :
576 0 : aCursor.X() -= aOffset.X() + mpFTChangeOrder->GetSizePixel().Width();
577 0 : aCursor.Y() += (aSize.Height() - mpFTChangeOrder->GetSizePixel().Height()) >> 1;
578 0 : mpFTChangeOrder->SetPosPixel( aCursor );
579 :
580 : // positionate the custom animation list control
581 0 : Size aCustomAnimationListSize( aPaneSize.Width() - aListPos.X() - aOffset.X(), aCursor.Y() - aListPos.Y() - 2 * aOffset.Y() );
582 0 : mpCustomAnimationList->SetPosSizePixel( aListPos, aCustomAnimationListSize );
583 0 : }
584 :
585 0 : static sal_Int32 getPropertyType( const OUString& rProperty )
586 : {
587 0 : if ( rProperty == "Direction" )
588 0 : return nPropertyTypeDirection;
589 :
590 0 : if ( rProperty == "Spokes" )
591 0 : return nPropertyTypeSpokes;
592 :
593 0 : if ( rProperty == "Zoom" )
594 0 : return nPropertyTypeZoom;
595 :
596 0 : if ( rProperty == "Accelerate" )
597 0 : return nPropertyTypeAccelerate;
598 :
599 0 : if ( rProperty == "Decelerate" )
600 0 : return nPropertyTypeDecelerate;
601 :
602 0 : if ( rProperty == "Color1" )
603 0 : return nPropertyTypeFirstColor;
604 :
605 0 : if ( rProperty == "Color2" )
606 0 : return nPropertyTypeSecondColor;
607 :
608 0 : if ( rProperty == "FillColor" )
609 0 : return nPropertyTypeFillColor;
610 :
611 0 : if ( rProperty == "ColorStyle" )
612 0 : return nPropertyTypeColorStyle;
613 :
614 0 : if ( rProperty == "AutoReverse" )
615 0 : return nPropertyTypeAutoReverse;
616 :
617 0 : if ( rProperty == "FontStyle" )
618 0 : return nPropertyTypeFont;
619 :
620 0 : if ( rProperty == "CharColor" )
621 0 : return nPropertyTypeCharColor;
622 :
623 0 : if ( rProperty == "CharHeight" )
624 0 : return nPropertyTypeCharHeight;
625 :
626 0 : if ( rProperty == "CharDecoration" )
627 0 : return nPropertyTypeCharDecoration;
628 :
629 0 : if ( rProperty == "LineColor" )
630 0 : return nPropertyTypeLineColor;
631 :
632 0 : if ( rProperty == "Rotate" )
633 0 : return nPropertyTypeRotate;
634 :
635 0 : if ( rProperty == "Transparency" )
636 0 : return nPropertyTypeTransparency;
637 :
638 0 : if ( rProperty == "Color" )
639 0 : return nPropertyTypeColor;
640 :
641 0 : if ( rProperty == "Scale" )
642 0 : return nPropertyTypeScale;
643 :
644 0 : return nPropertyTypeNone;
645 : }
646 :
647 0 : OUString getPropertyName( sal_Int32 nPropertyType )
648 : {
649 0 : switch( nPropertyType )
650 : {
651 : case nPropertyTypeDirection:
652 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_DIRECTION_PROPERTY ) ) );
653 :
654 : case nPropertyTypeSpokes:
655 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_SPOKES_PROPERTY ) ) );
656 :
657 : case nPropertyTypeFirstColor:
658 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FIRST_COLOR_PROPERTY ) ) );
659 :
660 : case nPropertyTypeSecondColor:
661 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_SECOND_COLOR_PROPERTY ) ) );
662 :
663 : case nPropertyTypeZoom:
664 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_ZOOM_PROPERTY ) ) );
665 :
666 : case nPropertyTypeFillColor:
667 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FILL_COLOR_PROPERTY ) ) );
668 :
669 : case nPropertyTypeColorStyle:
670 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_STYLE_PROPERTY ) ) );
671 :
672 : case nPropertyTypeFont:
673 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_PROPERTY ) ) );
674 :
675 : case nPropertyTypeCharHeight:
676 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_SIZE_PROPERTY ) ) );
677 :
678 : case nPropertyTypeCharColor:
679 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_COLOR_PROPERTY ) ) );
680 :
681 : case nPropertyTypeCharHeightStyle:
682 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_SIZE_STYLE_PROPERTY ) ) );
683 :
684 : case nPropertyTypeCharDecoration:
685 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_STYLE_PROPERTY ) ) );
686 :
687 : case nPropertyTypeLineColor:
688 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_LINE_COLOR_PROPERTY ) ) );
689 :
690 : case nPropertyTypeRotate:
691 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_AMOUNT_PROPERTY ) ) );
692 :
693 : case nPropertyTypeColor:
694 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_COLOR_PROPERTY ) ) );
695 :
696 : case nPropertyTypeTransparency:
697 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_AMOUNT_PROPERTY ) ) );
698 :
699 : case nPropertyTypeScale:
700 0 : return OUString( String( SdResId( STR_CUSTOMANIMATION_SCALE_PROPERTY ) ) );
701 : }
702 :
703 0 : OUString aStr;
704 0 : return aStr;
705 : }
706 :
707 0 : void CustomAnimationPane::updateControls()
708 : {
709 0 : mpFLModify->Enable( mxView.is() );
710 0 : mpFTSpeed->Enable( mxView.is() );
711 0 : mpCBSpeed->Enable( mxView.is() );
712 0 : mpCustomAnimationList->Enable( mxView.is() );
713 0 : mpFTChangeOrder->Enable( mxView.is() );
714 0 : mpPBMoveUp->Enable( mxView.is() );
715 0 : mpPBMoveDown->Enable( mxView.is() );
716 0 : mpFLSeparator1->Enable( mxView.is() );
717 0 : mpPBPlay->Enable( mxView.is() );
718 0 : mpPBSlideShow->Enable( mxView.is() );
719 0 : mpFLSeparator2->Enable( mxView.is() );
720 0 : mpCBAutoPreview->Enable( mxView.is() );
721 :
722 0 : if( !mxView.is() )
723 : {
724 0 : mpPBAddEffect->Enable( sal_False );
725 0 : mpPBChangeEffect->Enable( sal_False );
726 0 : mpPBRemoveEffect->Enable( sal_False );
727 0 : mpFLEffect->Enable( sal_False );
728 0 : mpFTStart->Enable( sal_False );
729 0 : mpLBStart->Enable( sal_False );
730 0 : mpPBPropertyMore->Enable( sal_False );
731 0 : mpLBProperty->Enable( sal_False );
732 0 : mpFTProperty->Enable( sal_False );
733 0 : mpCustomAnimationList->clear();
734 0 : return;
735 : }
736 :
737 0 : const int nSelectionCount = maListSelection.size();
738 :
739 0 : mpPBAddEffect->Enable( maViewSelection.hasValue() );
740 0 : mpPBChangeEffect->Enable( nSelectionCount);
741 0 : mpPBRemoveEffect->Enable(nSelectionCount);
742 :
743 0 : mpFLEffect->Enable(nSelectionCount > 0);
744 0 : mpFTStart->Enable(nSelectionCount > 0);
745 0 : mpLBStart->Enable(nSelectionCount > 0);
746 0 : mpPBPropertyMore->Enable(nSelectionCount > 0);
747 :
748 0 : mpFTProperty->SetText( maStrProperty );
749 :
750 0 : mnPropertyType = nPropertyTypeNone;
751 :
752 0 : if( nSelectionCount == 1 )
753 : {
754 0 : CustomAnimationEffectPtr pEffect = maListSelection.front();
755 :
756 0 : OUString aUIName( getPresets().getUINameForPresetId( pEffect->getPresetId() ) );
757 :
758 0 : OUString aTemp( maStrModify );
759 :
760 0 : if( !aUIName.isEmpty() )
761 : {
762 0 : aTemp += OUString( (sal_Unicode)' ' );
763 0 : aTemp += aUIName;
764 : }
765 0 : mpFLEffect->SetText( aTemp );
766 :
767 0 : CustomAnimationPresetPtr pDescriptor = getPresets().getEffectDescriptor( pEffect->getPresetId() );
768 0 : if( pDescriptor.get() )
769 : {
770 0 : PropertySubControl* pSubControl = NULL;
771 :
772 0 : Any aValue;
773 :
774 0 : UStringList aProperties( pDescriptor->getProperties() );
775 0 : if( aProperties.size() >= 1 )
776 : {
777 0 : mnPropertyType = getPropertyType( aProperties.front() );
778 :
779 0 : mpFTProperty->SetText( getPropertyName( mnPropertyType ) );
780 :
781 0 : aValue = getProperty1Value( mnPropertyType, pEffect );
782 : }
783 :
784 0 : if( aValue.hasValue() )
785 : {
786 0 : pSubControl = mpLBProperty->getSubControl();
787 0 : if( !pSubControl || (pSubControl->getControlType() != mnPropertyType) )
788 : {
789 0 : pSubControl = PropertySubControl::create( mnPropertyType, this, aValue, pEffect->getPresetId(), LINK( this, CustomAnimationPane, implPropertyHdl ) );
790 0 : mpLBProperty->setSubControl( pSubControl );
791 : }
792 : else
793 : {
794 0 : pSubControl->setValue( aValue, pEffect->getPresetId() );
795 : }
796 : }
797 : else
798 : {
799 0 : mpLBProperty->setSubControl( 0 );
800 : }
801 :
802 0 : bool bEnable = (pSubControl != 0) && (pSubControl->getControl()->IsEnabled());
803 0 : mpLBProperty->Enable( bEnable );
804 0 : mpFTProperty->Enable( bEnable );
805 : }
806 : else
807 : {
808 0 : mpLBProperty->setSubControl( 0 );
809 0 : mpFTProperty->Enable( sal_False );
810 0 : mpLBProperty->Enable( sal_False );
811 0 : mpPBPropertyMore->Enable( sal_False );
812 : }
813 :
814 0 : sal_uInt16 nPos = 0xffff;
815 :
816 0 : sal_Int16 nNodeType = pEffect->getNodeType();
817 0 : switch( nNodeType )
818 : {
819 0 : case EffectNodeType::ON_CLICK: nPos = 0; break;
820 0 : case EffectNodeType::WITH_PREVIOUS: nPos = 1; break;
821 0 : case EffectNodeType::AFTER_PREVIOUS: nPos = 2; break;
822 : }
823 :
824 0 : mpLBStart->SelectEntryPos( nPos );
825 :
826 0 : double fDuration = pEffect->getDuration();
827 0 : const bool bHasSpeed = fDuration > 0.001;
828 :
829 0 : mpFTSpeed->Enable(bHasSpeed);
830 0 : mpCBSpeed->Enable(bHasSpeed);
831 :
832 0 : if( bHasSpeed )
833 : {
834 0 : if( fDuration == 5.0 )
835 0 : nPos = 0;
836 0 : else if( fDuration == 3.0 )
837 0 : nPos = 1;
838 0 : else if( fDuration == 2.0 )
839 0 : nPos = 2;
840 0 : else if( fDuration == 1.0 )
841 0 : nPos = 3;
842 0 : else if( fDuration == 0.5 )
843 0 : nPos = 4;
844 : else
845 0 : nPos = 0xffff;
846 :
847 0 : mpCBSpeed->SelectEntryPos( nPos );
848 : }
849 :
850 0 : mpPBPropertyMore->Enable( sal_True );
851 :
852 0 : mpFTChangeOrder->Enable( sal_True );
853 : }
854 : else
855 : {
856 0 : mpLBProperty->setSubControl( 0 );
857 0 : mpFTProperty->Enable( sal_False );
858 0 : mpLBProperty->Enable( sal_False );
859 0 : mpPBPropertyMore->Enable( sal_False );
860 0 : mpFTSpeed->Enable(sal_False);
861 0 : mpCBSpeed->Enable(sal_False);
862 0 : mpFTChangeOrder->Enable( sal_False );
863 0 : mpLBStart->SetNoSelection();
864 0 : mpCBSpeed->SetNoSelection();
865 0 : mpFLEffect->SetText( maStrModify );
866 : }
867 :
868 0 : bool bEnableUp = true;
869 0 : bool bEnableDown = true;
870 0 : if( nSelectionCount == 0 )
871 : {
872 0 : bEnableUp = false;
873 0 : bEnableDown = false;
874 : }
875 : else
876 : {
877 0 : if( mpMainSequence->find( maListSelection.front() ) == mpMainSequence->getBegin() )
878 0 : bEnableUp = false;
879 :
880 0 : EffectSequence::iterator aIter( mpMainSequence->find( maListSelection.back() ) );
881 0 : if( aIter == mpMainSequence->getEnd() )
882 : {
883 0 : bEnableDown = false;
884 : }
885 : else
886 : {
887 0 : do
888 : {
889 0 : ++aIter;
890 : }
891 0 : while( (aIter != mpMainSequence->getEnd()) && !(mpCustomAnimationList->isExpanded((*aIter)) ) );
892 :
893 0 : if( aIter == mpMainSequence->getEnd() )
894 0 : bEnableDown = false;
895 : }
896 :
897 0 : if( bEnableUp || bEnableDown )
898 : {
899 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
900 :
901 0 : EffectSequenceHelper* pSequence = 0;
902 0 : EffectSequence::iterator aRebuildIter( maListSelection.begin() );
903 0 : const EffectSequence::iterator aRebuildEnd( maListSelection.end() );
904 0 : while( aRebuildIter != aRebuildEnd )
905 : {
906 0 : CustomAnimationEffectPtr pEffect = (*aRebuildIter++);
907 :
908 0 : if( pEffect.get() )
909 : {
910 0 : if( pSequence == 0 )
911 : {
912 0 : pSequence = pEffect->getEffectSequence();
913 : }
914 : else
915 : {
916 0 : if( pSequence != pEffect->getEffectSequence() )
917 : {
918 0 : bEnableUp = false;
919 0 : bEnableDown = false;
920 0 : break;
921 : }
922 : }
923 : }
924 0 : }
925 : }
926 : }
927 :
928 0 : mpPBMoveUp->Enable(bEnableUp);
929 0 : mpPBMoveDown->Enable(bEnableDown);
930 :
931 0 : SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
932 0 : mpCBAutoPreview->Check( pOptions->IsPreviewChangedEffects() == sal_True );
933 :
934 0 : updateMotionPathTags();
935 : }
936 :
937 0 : static bool updateMotionPathImpl( CustomAnimationPane& rPane, ::sd::View& rView, EffectSequence::iterator aIter, EffectSequence::iterator aEnd, MotionPathTagVector& rOldTags, MotionPathTagVector& rNewTags )
938 : {
939 0 : bool bChanges = false;
940 0 : while( aIter != aEnd )
941 : {
942 0 : CustomAnimationEffectPtr pEffect( (*aIter++) );
943 0 : if( pEffect.get() && pEffect->getPresetClass() == ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH )
944 : {
945 0 : rtl::Reference< MotionPathTag > xMotionPathTag;
946 : // first try to find if there is already a tag for this
947 0 : MotionPathTagVector::iterator aMIter( rOldTags.begin() );
948 0 : for( ; aMIter != rOldTags.end(); ++aMIter )
949 : {
950 0 : rtl::Reference< MotionPathTag > xTag( (*aMIter) );
951 0 : if( xTag->getEffect() == pEffect )
952 : {
953 0 : if( !xTag->isDisposed() )
954 : {
955 0 : xMotionPathTag = xTag;
956 0 : rOldTags.erase( aMIter );
957 : }
958 0 : break;
959 : }
960 0 : }
961 :
962 : // if not found, create new one
963 0 : if( !xMotionPathTag.is() )
964 : {
965 0 : xMotionPathTag.set( new MotionPathTag( rPane, rView, pEffect ) );
966 0 : bChanges = true;
967 : }
968 :
969 0 : if( xMotionPathTag.is() )
970 0 : rNewTags.push_back( xMotionPathTag );
971 : }
972 0 : }
973 :
974 0 : return bChanges;
975 : }
976 :
977 0 : void CustomAnimationPane::updateMotionPathTags()
978 : {
979 0 : bool bChanges = false;
980 :
981 0 : MotionPathTagVector aTags;
982 0 : aTags.swap( maMotionPathTags );
983 :
984 0 : ::sd::View* pView = 0;
985 :
986 0 : if( mxView.is() )
987 : {
988 0 : ::boost::shared_ptr<ViewShell> xViewShell( mrBase.GetMainViewShell() );
989 0 : if( xViewShell.get() )
990 0 : pView = xViewShell->GetView();
991 : }
992 :
993 0 : if( IsVisible() && mpMainSequence.get() && pView )
994 : {
995 0 : bChanges = updateMotionPathImpl( *this, *pView, mpMainSequence->getBegin(), mpMainSequence->getEnd(), aTags, maMotionPathTags );
996 :
997 0 : const InteractiveSequenceList& rISL = mpMainSequence->getInteractiveSequenceList();
998 0 : InteractiveSequenceList::const_iterator aISI( rISL.begin() );
999 0 : while( aISI != rISL.end() )
1000 : {
1001 0 : InteractiveSequencePtr pIS( (*aISI++) );
1002 0 : bChanges |= updateMotionPathImpl( *this, *pView, pIS->getBegin(), pIS->getEnd(), aTags, maMotionPathTags );
1003 0 : }
1004 : }
1005 :
1006 0 : if( !aTags.empty() )
1007 : {
1008 0 : bChanges = true;
1009 0 : MotionPathTagVector::iterator aIter( aTags.begin() );
1010 0 : while( aIter != aTags.end() )
1011 : {
1012 0 : rtl::Reference< MotionPathTag > xTag( (*aIter++) );
1013 0 : xTag->Dispose();
1014 0 : }
1015 : }
1016 :
1017 0 : if( bChanges && pView )
1018 0 : pView->updateHandles();
1019 0 : }
1020 :
1021 0 : void CustomAnimationPane::onSelectionChanged()
1022 : {
1023 0 : if( !maSelectionLock.isLocked() )
1024 : {
1025 0 : ScopeLockGuard aGuard( maSelectionLock );
1026 :
1027 0 : if( mxView.is() ) try
1028 : {
1029 0 : Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
1030 0 : if (xSel.is())
1031 : {
1032 0 : maViewSelection = xSel->getSelection();
1033 0 : mpCustomAnimationList->onSelectionChanged( maViewSelection );
1034 0 : updateControls();
1035 0 : }
1036 : }
1037 0 : catch( Exception& )
1038 : {
1039 : OSL_FAIL( "sd::CustomAnimationPane::onSelectionChanged(), Exception caught!" );
1040 0 : }
1041 : }
1042 0 : }
1043 :
1044 0 : void CustomAnimationPane::onDoubleClick()
1045 : {
1046 0 : showOptions();
1047 0 : }
1048 :
1049 0 : void CustomAnimationPane::onContextMenu( sal_uInt16 nSelectedPopupEntry )
1050 : {
1051 0 : switch( nSelectedPopupEntry )
1052 : {
1053 0 : case CM_WITH_CLICK: onChangeStart( EffectNodeType::ON_CLICK ); break;
1054 0 : case CM_WITH_PREVIOUS: onChangeStart( EffectNodeType::WITH_PREVIOUS ); break;
1055 0 : case CM_AFTER_PREVIOUS: onChangeStart( EffectNodeType::AFTER_PREVIOUS ); break;
1056 0 : case CM_OPTIONS: showOptions(); break;
1057 0 : case CM_DURATION: showOptions(RID_TP_CUSTOMANIMATION_DURATION); break;
1058 0 : case CM_REMOVE: onRemove(); break;
1059 0 : case CM_CREATE: if( maViewSelection.hasValue() ) onChange( true ); break;
1060 : }
1061 :
1062 0 : updateControls();
1063 0 : }
1064 :
1065 :
1066 :
1067 :
1068 0 : void CustomAnimationPane::DataChanged (const DataChangedEvent& rEvent)
1069 : {
1070 : (void)rEvent;
1071 0 : UpdateLook();
1072 0 : }
1073 :
1074 :
1075 :
1076 :
1077 0 : void CustomAnimationPane::UpdateLook (void)
1078 : {
1079 : const Wallpaper aBackground (
1080 : ::sfx2::sidebar::Theme::GetWallpaper(
1081 0 : ::sfx2::sidebar::Theme::Paint_PanelBackground));
1082 0 : SetBackground(aBackground);
1083 0 : if (mpFLModify != NULL)
1084 0 : mpFLModify->SetBackground(aBackground);
1085 0 : if (mpFLEffect != NULL)
1086 0 : mpFLEffect->SetBackground(aBackground);
1087 0 : if (mpFTStart != NULL)
1088 0 : mpFTStart->SetBackground(aBackground);
1089 0 : if (mpFTProperty != NULL)
1090 0 : mpFTProperty->SetBackground(aBackground);
1091 0 : if (mpFTSpeed != NULL)
1092 0 : mpFTSpeed->SetBackground(aBackground);
1093 0 : if (mpFTChangeOrder != NULL)
1094 0 : mpFTChangeOrder->SetBackground(aBackground);
1095 0 : if (mpFLSeparator1 != NULL)
1096 0 : mpFLSeparator1->SetBackground(aBackground);
1097 0 : if (mpFLSeparator2 != NULL)
1098 0 : mpFLSeparator2->SetBackground(aBackground);
1099 0 : }
1100 :
1101 :
1102 :
1103 :
1104 0 : void addValue( STLPropertySet* pSet, sal_Int32 nHandle, const Any& rValue )
1105 : {
1106 0 : switch( pSet->getPropertyState( nHandle ) )
1107 : {
1108 : case STLPropertyState_AMBIGUOUS:
1109 : // value is already ambiguous, do nothing
1110 0 : break;
1111 : case STLPropertyState_DIRECT:
1112 : // set to ambiguous if existing value is different
1113 0 : if( rValue != pSet->getPropertyValue( nHandle ) )
1114 0 : pSet->setPropertyState( nHandle, STLPropertyState_AMBIGUOUS );
1115 0 : break;
1116 : case STLPropertyState_DEFAULT:
1117 : // just set new value
1118 0 : pSet->setPropertyValue( nHandle, rValue );
1119 0 : break;
1120 : }
1121 0 : }
1122 :
1123 0 : static sal_Int32 calcMaxParaDepth( Reference< XShape > xTargetShape )
1124 : {
1125 0 : sal_Int32 nMaxParaDepth = -1;
1126 :
1127 0 : if( xTargetShape.is() )
1128 : {
1129 0 : Reference< XEnumerationAccess > xText( xTargetShape, UNO_QUERY );
1130 0 : if( xText.is() )
1131 : {
1132 0 : Reference< XPropertySet > xParaSet;
1133 0 : const OUString strNumberingLevel( "NumberingLevel" );
1134 :
1135 0 : Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW );
1136 0 : while( xEnumeration->hasMoreElements() )
1137 : {
1138 0 : xEnumeration->nextElement() >>= xParaSet;
1139 0 : if( xParaSet.is() )
1140 : {
1141 0 : sal_Int32 nParaDepth = 0;
1142 0 : xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth;
1143 :
1144 0 : if( nParaDepth > nMaxParaDepth )
1145 0 : nMaxParaDepth = nParaDepth;
1146 : }
1147 0 : }
1148 0 : }
1149 : }
1150 :
1151 0 : return nMaxParaDepth + 1;
1152 : }
1153 :
1154 0 : Any CustomAnimationPane::getProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect )
1155 : {
1156 0 : switch( nType )
1157 : {
1158 : case nPropertyTypeDirection:
1159 : case nPropertyTypeSpokes:
1160 : case nPropertyTypeZoom:
1161 0 : return makeAny( pEffect->getPresetSubType() );
1162 :
1163 : case nPropertyTypeColor:
1164 : case nPropertyTypeFillColor:
1165 : case nPropertyTypeFirstColor:
1166 : case nPropertyTypeSecondColor:
1167 : case nPropertyTypeCharColor:
1168 : case nPropertyTypeLineColor:
1169 : {
1170 0 : const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
1171 0 : return pEffect->getColor( nIndex );
1172 : }
1173 :
1174 : case nPropertyTypeFont:
1175 0 : return pEffect->getProperty( AnimationNodeType::SET, "CharFontName" , VALUE_TO );
1176 :
1177 : case nPropertyTypeCharHeight:
1178 : {
1179 0 : const OUString aAttributeName( "CharHeight" );
1180 0 : Any aValue( pEffect->getProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO ) );
1181 0 : if( !aValue.hasValue() )
1182 0 : aValue = pEffect->getProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO );
1183 0 : return aValue;
1184 : }
1185 :
1186 : case nPropertyTypeRotate:
1187 0 : return pEffect->getTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY);
1188 :
1189 : case nPropertyTypeTransparency:
1190 0 : return pEffect->getProperty( AnimationNodeType::SET, "Opacity" , VALUE_TO );
1191 :
1192 : case nPropertyTypeScale:
1193 0 : return pEffect->getTransformationProperty( AnimationTransformType::SCALE, VALUE_BY );
1194 :
1195 : case nPropertyTypeCharDecoration:
1196 : {
1197 0 : Sequence< Any > aValues(3);
1198 0 : aValues[0] = pEffect->getProperty( AnimationNodeType::SET, "CharWeight" , VALUE_TO );
1199 0 : aValues[1] = pEffect->getProperty( AnimationNodeType::SET, "CharPosture" , VALUE_TO );
1200 0 : aValues[2] = pEffect->getProperty( AnimationNodeType::SET, "CharUnderline" , VALUE_TO );
1201 0 : return makeAny( aValues );
1202 : }
1203 : }
1204 :
1205 0 : Any aAny;
1206 0 : return aAny;
1207 : }
1208 :
1209 0 : bool CustomAnimationPane::setProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect, const Any& rValue )
1210 : {
1211 0 : bool bEffectChanged = false;
1212 0 : switch( nType )
1213 : {
1214 : case nPropertyTypeDirection:
1215 : case nPropertyTypeSpokes:
1216 : case nPropertyTypeZoom:
1217 : {
1218 0 : OUString aPresetSubType;
1219 0 : rValue >>= aPresetSubType;
1220 0 : if( aPresetSubType != pEffect->getPresetSubType() )
1221 : {
1222 0 : getPresets().changePresetSubType( pEffect, aPresetSubType );
1223 0 : bEffectChanged = true;
1224 0 : }
1225 : }
1226 0 : break;
1227 :
1228 : case nPropertyTypeFillColor:
1229 : case nPropertyTypeColor:
1230 : case nPropertyTypeFirstColor:
1231 : case nPropertyTypeSecondColor:
1232 : case nPropertyTypeCharColor:
1233 : case nPropertyTypeLineColor:
1234 : {
1235 0 : const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
1236 0 : Any aOldColor( pEffect->getColor( nIndex ) );
1237 0 : if( aOldColor != rValue )
1238 : {
1239 0 : pEffect->setColor( nIndex, rValue );
1240 0 : bEffectChanged = true;
1241 0 : }
1242 : }
1243 0 : break;
1244 :
1245 : case nPropertyTypeFont:
1246 0 : bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "CharFontName" , VALUE_TO, rValue );
1247 0 : break;
1248 :
1249 : case nPropertyTypeCharHeight:
1250 : {
1251 0 : const OUString aAttributeName( "CharHeight" );
1252 0 : bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO, rValue );
1253 0 : if( !bEffectChanged )
1254 0 : bEffectChanged = pEffect->setProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO, rValue );
1255 : }
1256 0 : break;
1257 : case nPropertyTypeRotate:
1258 0 : bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY , rValue );
1259 0 : break;
1260 :
1261 : case nPropertyTypeTransparency:
1262 0 : bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "Opacity" , VALUE_TO, rValue );
1263 0 : break;
1264 :
1265 : case nPropertyTypeScale:
1266 0 : bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::SCALE, VALUE_BY, rValue );
1267 0 : break;
1268 :
1269 : case nPropertyTypeCharDecoration:
1270 : {
1271 0 : Sequence< Any > aValues(3);
1272 0 : rValue >>= aValues;
1273 0 : bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "CharWeight" , VALUE_TO, aValues[0] );
1274 0 : bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, "CharPosture" , VALUE_TO, aValues[1] );
1275 0 : bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, "CharUnderline" , VALUE_TO, aValues[2] );
1276 : }
1277 0 : break;
1278 :
1279 : }
1280 :
1281 0 : return bEffectChanged;
1282 : }
1283 :
1284 0 : static sal_Bool hasVisibleShape( const Reference< XShape >& xShape )
1285 : {
1286 : try
1287 : {
1288 0 : const OUString sShapeType( xShape->getShapeType() );
1289 :
1290 0 : if( sShapeType == "com.sun.star.presentation.TitleTextShape" || sShapeType == "com.sun.star.presentation.OutlinerShape" ||
1291 0 : sShapeType == "com.sun.star.presentation.SubtitleShape" || sShapeType == "com.sun.star.drawing.TextShape" )
1292 : {
1293 0 : const OUString sFillStyle( "FillStyle" );
1294 0 : const OUString sLineStyle( "LineStyle" );
1295 0 : Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW );
1296 :
1297 : FillStyle eFillStyle;
1298 0 : xSet->getPropertyValue( sFillStyle ) >>= eFillStyle;
1299 :
1300 : ::com::sun::star::drawing::LineStyle eLineStyle;
1301 0 : xSet->getPropertyValue( sLineStyle ) >>= eLineStyle;
1302 :
1303 0 : return eFillStyle != FillStyle_NONE || eLineStyle != ::com::sun::star::drawing::LineStyle_NONE;
1304 0 : }
1305 : }
1306 0 : catch( Exception& )
1307 : {
1308 : }
1309 0 : return sal_True;
1310 : }
1311 :
1312 0 : STLPropertySet* CustomAnimationPane::createSelectionSet()
1313 : {
1314 0 : STLPropertySet* pSet = CustomAnimationDialog::createDefaultSet();
1315 :
1316 0 : pSet->setPropertyValue( nHandleCurrentPage, makeAny( mxCurrentPage ) );
1317 :
1318 0 : sal_Int32 nMaxParaDepth = 0;
1319 :
1320 : // get options from selected effects
1321 0 : EffectSequence::iterator aIter( maListSelection.begin() );
1322 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
1323 0 : const CustomAnimationPresets& rPresets (getPresets());
1324 0 : while( aIter != aEnd )
1325 : {
1326 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
1327 :
1328 0 : EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1329 0 : if( !pEffectSequence )
1330 0 : pEffectSequence = mpMainSequence.get();
1331 :
1332 0 : if( pEffect->hasText() )
1333 : {
1334 0 : sal_Int32 n = calcMaxParaDepth(pEffect->getTargetShape());
1335 0 : if( n > nMaxParaDepth )
1336 0 : nMaxParaDepth = n;
1337 : }
1338 :
1339 0 : addValue( pSet, nHandleHasAfterEffect, makeAny( pEffect->hasAfterEffect() ) );
1340 0 : addValue( pSet, nHandleAfterEffectOnNextEffect, makeAny( pEffect->IsAfterEffectOnNext() ? sal_True : sal_False ) );
1341 0 : addValue( pSet, nHandleDimColor, pEffect->getDimColor() );
1342 0 : addValue( pSet, nHandleIterateType, makeAny( pEffect->getIterateType() ) );
1343 :
1344 : // convert absolute time to percentage value
1345 : // This calculation is done in float to avoid some rounding artifacts.
1346 0 : float fIterateInterval = (float)pEffect->getIterateInterval();
1347 0 : if( pEffect->getDuration() )
1348 0 : fIterateInterval = (float)(fIterateInterval / pEffect->getDuration() );
1349 0 : fIterateInterval *= 100.0;
1350 0 : addValue( pSet, nHandleIterateInterval, makeAny( (double)fIterateInterval ) );
1351 :
1352 0 : addValue( pSet, nHandleBegin, makeAny( pEffect->getBegin() ) );
1353 0 : addValue( pSet, nHandleDuration, makeAny( pEffect->getDuration() ) );
1354 0 : addValue( pSet, nHandleStart, makeAny( pEffect->getNodeType() ) );
1355 0 : addValue( pSet, nHandleRepeat, makeAny( pEffect->getRepeatCount() ) );
1356 0 : addValue( pSet, nHandleEnd, pEffect->getEnd() );
1357 0 : addValue( pSet, nHandleRewind, makeAny( pEffect->getFill() ) );
1358 :
1359 0 : addValue( pSet, nHandlePresetId, makeAny( pEffect->getPresetId() ) );
1360 :
1361 0 : addValue( pSet, nHandleHasText, makeAny( (sal_Bool)pEffect->hasText() ) );
1362 :
1363 0 : addValue( pSet, nHandleHasVisibleShape, Any( hasVisibleShape( pEffect->getTargetShape() ) ) );
1364 :
1365 0 : Any aSoundSource;
1366 0 : if( pEffect->getAudio().is() )
1367 : {
1368 0 : aSoundSource = pEffect->getAudio()->getSource();
1369 0 : addValue( pSet, nHandleSoundVolumne, makeAny( pEffect->getAudio()->getVolume() ) );
1370 : // todo addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) );
1371 : // this is now stored at the XCommand parameter sequence
1372 : }
1373 0 : else if( pEffect->getCommand() == EffectCommands::STOPAUDIO )
1374 : {
1375 0 : aSoundSource = makeAny( (sal_Bool)sal_True );
1376 : }
1377 0 : addValue( pSet, nHandleSoundURL, aSoundSource );
1378 :
1379 0 : sal_Int32 nGroupId = pEffect->getGroupId();
1380 0 : CustomAnimationTextGroupPtr pTextGroup;
1381 0 : if( nGroupId != -1 )
1382 0 : pTextGroup = pEffectSequence->findGroup( nGroupId );
1383 :
1384 0 : addValue( pSet, nHandleTextGrouping, makeAny( pTextGroup.get() ? pTextGroup->getTextGrouping() : (sal_Int32)-1 ) );
1385 0 : addValue( pSet, nHandleAnimateForm, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getAnimateForm() : sal_True ) );
1386 0 : addValue( pSet, nHandleTextGroupingAuto, makeAny( pTextGroup.get() ? pTextGroup->getTextGroupingAuto() : (double)-1.0 ) );
1387 0 : addValue( pSet, nHandleTextReverse, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getTextReverse() : sal_False ) );
1388 :
1389 0 : if( pEffectSequence->getSequenceType() == EffectNodeType::INTERACTIVE_SEQUENCE )
1390 : {
1391 0 : InteractiveSequence* pIS = static_cast< InteractiveSequence* >( pEffectSequence );
1392 0 : addValue( pSet, nHandleTrigger, makeAny( pIS->getTriggerShape() ) );
1393 : }
1394 :
1395 0 : CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( pEffect->getPresetId() );
1396 0 : if( pDescriptor.get() )
1397 : {
1398 0 : sal_Int32 nType = nPropertyTypeNone;
1399 :
1400 0 : UStringList aProperties( pDescriptor->getProperties() );
1401 0 : if( aProperties.size() >= 1 )
1402 0 : nType = getPropertyType( aProperties.front() );
1403 :
1404 0 : if( nType != nPropertyTypeNone )
1405 : {
1406 0 : addValue( pSet, nHandleProperty1Type, makeAny( nType ) );
1407 0 : addValue( pSet, nHandleProperty1Value, getProperty1Value( nType, pEffect ) );
1408 : }
1409 :
1410 0 : if( pDescriptor->hasProperty( "Accelerate" ) )
1411 : {
1412 0 : addValue( pSet, nHandleAccelerate, makeAny( pEffect->getAcceleration() ) );
1413 : }
1414 :
1415 0 : if( pDescriptor->hasProperty( "Decelerate" ) )
1416 : {
1417 0 : addValue( pSet, nHandleDecelerate, makeAny( pEffect->getDecelerate() ) );
1418 : }
1419 :
1420 0 : if( pDescriptor->hasProperty( "AutoReverse" ) )
1421 : {
1422 0 : addValue( pSet, nHandleAutoReverse, makeAny( pEffect->getAutoReverse() ) );
1423 0 : }
1424 : }
1425 0 : }
1426 :
1427 0 : addValue( pSet, nHandleMaxParaDepth, makeAny( nMaxParaDepth ) );
1428 :
1429 0 : return pSet;
1430 : }
1431 :
1432 0 : void CustomAnimationPane::changeSelection( STLPropertySet* pResultSet, STLPropertySet* pOldSet )
1433 : {
1434 : // change selected effect
1435 0 : bool bChanged = false;
1436 :
1437 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
1438 :
1439 0 : EffectSequence::iterator aIter( maListSelection.begin() );
1440 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
1441 0 : while( aIter != aEnd )
1442 : {
1443 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
1444 :
1445 : DBG_ASSERT( pEffect->getEffectSequence(), "sd::CustomAnimationPane::changeSelection(), dead effect in selection!" );
1446 0 : if( !pEffect->getEffectSequence() )
1447 0 : continue;
1448 :
1449 0 : double fDuration = 0.0; // we might need this for iterate-interval
1450 0 : if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1451 : {
1452 0 : pResultSet->getPropertyValue( nHandleDuration ) >>= fDuration;
1453 : }
1454 : else
1455 : {
1456 0 : fDuration = pEffect->getDuration();
1457 : }
1458 :
1459 0 : if( pResultSet->getPropertyState( nHandleIterateType ) == STLPropertyState_DIRECT )
1460 : {
1461 0 : sal_Int16 nIterateType = 0;
1462 0 : pResultSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
1463 0 : if( pEffect->getIterateType() != nIterateType )
1464 : {
1465 0 : pEffect->setIterateType( nIterateType );
1466 0 : bChanged = true;
1467 : }
1468 : }
1469 :
1470 0 : if( pEffect->getIterateType() )
1471 : {
1472 0 : if( pResultSet->getPropertyState( nHandleIterateInterval ) == STLPropertyState_DIRECT )
1473 : {
1474 0 : double fIterateInterval = 0.0;
1475 0 : pResultSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
1476 0 : if( pEffect->getIterateInterval() != fIterateInterval )
1477 : {
1478 0 : const double f = fIterateInterval * pEffect->getDuration() / 100;
1479 0 : pEffect->setIterateInterval( f );
1480 0 : bChanged = true;
1481 : }
1482 : }
1483 : }
1484 :
1485 0 : if( pResultSet->getPropertyState( nHandleBegin ) == STLPropertyState_DIRECT )
1486 : {
1487 0 : double fBegin = 0.0;
1488 0 : pResultSet->getPropertyValue( nHandleBegin ) >>= fBegin;
1489 0 : if( pEffect->getBegin() != fBegin )
1490 : {
1491 0 : pEffect->setBegin( fBegin );
1492 0 : bChanged = true;
1493 : }
1494 : }
1495 :
1496 0 : if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1497 : {
1498 0 : if( pEffect->getDuration() != fDuration )
1499 : {
1500 0 : pEffect->setDuration( fDuration );
1501 0 : bChanged = true;
1502 : }
1503 : }
1504 :
1505 0 : if( pResultSet->getPropertyState( nHandleStart ) == STLPropertyState_DIRECT )
1506 : {
1507 0 : sal_Int16 nNodeType = 0;
1508 0 : pResultSet->getPropertyValue( nHandleStart ) >>= nNodeType;
1509 0 : if( pEffect->getNodeType() != nNodeType )
1510 : {
1511 0 : pEffect->setNodeType( nNodeType );
1512 0 : bChanged = true;
1513 : }
1514 : }
1515 :
1516 0 : if( pResultSet->getPropertyState( nHandleRepeat ) == STLPropertyState_DIRECT )
1517 : {
1518 0 : Any aRepeatCount( pResultSet->getPropertyValue( nHandleRepeat ) );
1519 0 : if( aRepeatCount != pEffect->getRepeatCount() )
1520 : {
1521 0 : pEffect->setRepeatCount( aRepeatCount );
1522 0 : bChanged = true;
1523 0 : }
1524 : }
1525 :
1526 0 : if( pResultSet->getPropertyState( nHandleEnd ) == STLPropertyState_DIRECT )
1527 : {
1528 0 : Any aEndValue( pResultSet->getPropertyValue( nHandleEnd ) );
1529 0 : if( pEffect->getEnd() != aEndValue )
1530 : {
1531 0 : pEffect->setEnd( aEndValue );
1532 0 : bChanged = true;
1533 0 : }
1534 : }
1535 :
1536 0 : if( pResultSet->getPropertyState( nHandleRewind ) == STLPropertyState_DIRECT )
1537 : {
1538 0 : sal_Int16 nFill = 0;
1539 0 : pResultSet->getPropertyValue( nHandleRewind ) >>= nFill;
1540 0 : if( pEffect->getFill() != nFill )
1541 : {
1542 0 : pEffect->setFill( nFill );
1543 0 : bChanged = true;
1544 : }
1545 : }
1546 :
1547 0 : if( pResultSet->getPropertyState( nHandleHasAfterEffect ) == STLPropertyState_DIRECT )
1548 : {
1549 0 : sal_Bool bHasAfterEffect = sal_False;
1550 0 : if( pResultSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect )
1551 : {
1552 0 : if( pEffect->hasAfterEffect() != bHasAfterEffect )
1553 : {
1554 0 : pEffect->setHasAfterEffect( bHasAfterEffect );
1555 0 : bChanged = true;
1556 : }
1557 : }
1558 : }
1559 :
1560 0 : if( pResultSet->getPropertyState( nHandleAfterEffectOnNextEffect ) == STLPropertyState_DIRECT )
1561 : {
1562 0 : sal_Bool bAfterEffectOnNextEffect = sal_False;
1563 0 : if( (pResultSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextEffect) && ((pEffect->IsAfterEffectOnNext() ? sal_True : sal_False) != bAfterEffectOnNextEffect) )
1564 : {
1565 0 : pEffect->setAfterEffectOnNext( bAfterEffectOnNextEffect );
1566 0 : bChanged = true;
1567 : }
1568 : }
1569 :
1570 0 : if( pResultSet->getPropertyState( nHandleDimColor ) == STLPropertyState_DIRECT )
1571 : {
1572 0 : Any aDimColor( pResultSet->getPropertyValue( nHandleDimColor ) );
1573 0 : if( pEffect->getDimColor() != aDimColor )
1574 : {
1575 0 : pEffect->setDimColor( aDimColor );
1576 0 : bChanged = true;
1577 0 : }
1578 : }
1579 :
1580 0 : if( pResultSet->getPropertyState( nHandleAccelerate ) == STLPropertyState_DIRECT )
1581 : {
1582 0 : double fAccelerate = 0.0;
1583 0 : pResultSet->getPropertyValue( nHandleAccelerate ) >>= fAccelerate;
1584 0 : if( pEffect->getAcceleration() != fAccelerate )
1585 : {
1586 0 : pEffect->setAcceleration( fAccelerate );
1587 0 : bChanged = true;
1588 : }
1589 : }
1590 :
1591 0 : if( pResultSet->getPropertyState( nHandleDecelerate ) == STLPropertyState_DIRECT )
1592 : {
1593 0 : double fDecelerate = 0.0;
1594 0 : pResultSet->getPropertyValue( nHandleDecelerate ) >>= fDecelerate;
1595 0 : if( pEffect->getDecelerate() != fDecelerate )
1596 : {
1597 0 : pEffect->setDecelerate( fDecelerate );
1598 0 : bChanged = true;
1599 : }
1600 : }
1601 :
1602 0 : if( pResultSet->getPropertyState( nHandleAutoReverse ) == STLPropertyState_DIRECT )
1603 : {
1604 0 : sal_Bool bAutoReverse = sal_False;
1605 0 : pResultSet->getPropertyValue( nHandleAutoReverse ) >>= bAutoReverse;
1606 0 : if( pEffect->getAutoReverse() != bAutoReverse )
1607 : {
1608 0 : pEffect->setAutoReverse( bAutoReverse );
1609 0 : bChanged = true;
1610 : }
1611 : }
1612 :
1613 0 : if( pResultSet->getPropertyState( nHandleProperty1Value ) == STLPropertyState_DIRECT )
1614 : {
1615 0 : sal_Int32 nType = 0;
1616 0 : pOldSet->getPropertyValue( nHandleProperty1Type ) >>= nType;
1617 :
1618 0 : bChanged |= setProperty1Value( nType, pEffect, pResultSet->getPropertyValue( nHandleProperty1Value ) );
1619 : }
1620 :
1621 0 : if( pResultSet->getPropertyState( nHandleSoundURL ) == STLPropertyState_DIRECT )
1622 : {
1623 0 : const Any aSoundSource( pResultSet->getPropertyValue( nHandleSoundURL ) );
1624 :
1625 0 : if( aSoundSource.getValueType() == ::getCppuType((const sal_Bool*)0) )
1626 : {
1627 0 : pEffect->setStopAudio();
1628 0 : bChanged = true;
1629 : }
1630 : else
1631 : {
1632 0 : OUString aSoundURL;
1633 0 : aSoundSource >>= aSoundURL;
1634 :
1635 0 : if( !aSoundURL.isEmpty() )
1636 : {
1637 0 : if( !pEffect->getAudio().is() )
1638 : {
1639 0 : pEffect->createAudio( aSoundSource );
1640 0 : bChanged = true;
1641 : }
1642 : else
1643 : {
1644 0 : if( pEffect->getAudio()->getSource() != aSoundSource )
1645 : {
1646 0 : pEffect->getAudio()->setSource( aSoundSource );
1647 0 : bChanged = true;
1648 : }
1649 : }
1650 : }
1651 : else
1652 : {
1653 0 : if( pEffect->getAudio().is() || pEffect->getStopAudio() )
1654 : {
1655 0 : pEffect->removeAudio();
1656 0 : bChanged = true;
1657 : }
1658 0 : }
1659 0 : }
1660 : }
1661 :
1662 0 : if( pResultSet->getPropertyState( nHandleTrigger ) == STLPropertyState_DIRECT )
1663 : {
1664 0 : Reference< XShape > xTriggerShape;
1665 0 : pResultSet->getPropertyValue( nHandleTrigger ) >>= xTriggerShape;
1666 0 : bChanged |= mpMainSequence->setTrigger( pEffect, xTriggerShape );
1667 : }
1668 0 : }
1669 :
1670 0 : const bool bHasTextGrouping = pResultSet->getPropertyState( nHandleTextGrouping ) == STLPropertyState_DIRECT;
1671 0 : const bool bHasAnimateForm = pResultSet->getPropertyState( nHandleAnimateForm ) == STLPropertyState_DIRECT;
1672 0 : const bool bHasTextGroupingAuto = pResultSet->getPropertyState( nHandleTextGroupingAuto ) == STLPropertyState_DIRECT;
1673 0 : const bool bHasTextReverse = pResultSet->getPropertyState( nHandleTextReverse ) == STLPropertyState_DIRECT;
1674 :
1675 0 : if( bHasTextGrouping || bHasAnimateForm || bHasTextGroupingAuto || bHasTextReverse )
1676 : {
1677 : // we need to do a second pass for text grouping options
1678 : // since changing them can cause effects to be removed
1679 : // or replaced, we do this after we aplied all other options
1680 : // above
1681 :
1682 0 : sal_Int32 nTextGrouping = 0;
1683 0 : sal_Bool bAnimateForm = sal_True, bTextReverse = sal_False;
1684 0 : double fTextGroupingAuto = -1.0;
1685 :
1686 0 : if( bHasTextGrouping )
1687 0 : pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping;
1688 :
1689 0 : if( bHasAnimateForm )
1690 0 : pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm;
1691 :
1692 0 : if( bHasTextGroupingAuto )
1693 0 : pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto;
1694 :
1695 0 : if( bHasTextReverse )
1696 0 : pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse;
1697 :
1698 0 : EffectSequence const aSelectedEffects( maListSelection );
1699 0 : EffectSequence::const_iterator iter( aSelectedEffects.begin() );
1700 0 : const EffectSequence::const_iterator iEnd( aSelectedEffects.end() );
1701 0 : while( iter != iEnd )
1702 : {
1703 0 : CustomAnimationEffectPtr const& pEffect = (*iter++);
1704 :
1705 0 : EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1706 0 : if( !pEffectSequence )
1707 0 : pEffectSequence = mpMainSequence.get();
1708 :
1709 0 : sal_Int32 nGroupId = pEffect->getGroupId();
1710 0 : CustomAnimationTextGroupPtr pTextGroup;
1711 0 : if( (nGroupId != -1) )
1712 : {
1713 : // use existing group
1714 0 : pTextGroup = pEffectSequence->findGroup( nGroupId );
1715 : }
1716 : else
1717 : {
1718 : // somethings changed so we need a group now
1719 0 : pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse );
1720 0 : bChanged = true;
1721 : }
1722 :
1723 : //#i119988#
1724 : /************************************************************************/
1725 : /*
1726 : Note, the setAnimateForm means set the animation from TextGroup to Object's Shape
1727 : And on the UI in means "Animate attached shape" in "Effect Option" dialog
1728 : The setTextGrouping means set animation to Object's Text,
1729 : the nTextGrouping is Text Animation Type
1730 : nTextGrouping = -1 is "As one Object", means no text animation.
1731 :
1732 : The previous call order first do the setTextGrouping and then do the setAnimateForm,
1733 : that will cause such defect: in the setTextGrouping, the effect has been removed,
1734 : but in setAnimateForm still need this effect, then a NULL pointer of that effect will
1735 : be gotten, and cause crash.
1736 :
1737 : []bHasAnimateForm means the UI has changed, bAnimateForm is it value
1738 :
1739 : So if create a new textgroup animation, the following animation will never be run!
1740 : Since the \A1\B0Animate attached shape\A1\B1 is default checked.
1741 : And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false,
1742 : it same as the TextGroup\A1\AFs default value, also could not be run setAnimateForm.
1743 : if( bHasAnimateForm )
1744 : {
1745 : if( pTextGroup->getAnimateForm() != bAnimateForm )
1746 : {
1747 : pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1748 : bChanged = true;
1749 : }
1750 : }
1751 :
1752 : In setTextGrouping, there are three case:
1753 : 1. Create new text effects for empty TextGroup
1754 : 2. Remove all text effects of TextGroup (nTextGrouping == -1)
1755 : 3. Change all the text effects\A1\AF start type
1756 :
1757 : So here is the right logic:
1758 : If set the animation from text to shape and remove text animation,
1759 : should do setAnimateForm first, then do setTextGrouping.
1760 : Other case,do setTextGrouping first, then do setAnimateForm.
1761 :
1762 : */
1763 : /************************************************************************/
1764 :
1765 0 : bool bDoSetAnimateFormFirst = false;
1766 0 : bool bNeedDoSetAnimateForm = false;
1767 :
1768 0 : if( bHasAnimateForm )
1769 : {
1770 0 : if( pTextGroup->getAnimateForm() != bAnimateForm )
1771 : {
1772 0 : if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) )
1773 : {
1774 0 : bDoSetAnimateFormFirst = true;
1775 : }
1776 0 : bNeedDoSetAnimateForm = true;
1777 : }
1778 : }
1779 :
1780 0 : if (bDoSetAnimateFormFirst)
1781 : {
1782 0 : pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1783 0 : bChanged = true;
1784 : }
1785 :
1786 0 : if( bHasTextGrouping )
1787 : {
1788 0 : if( (pTextGroup->getTextGrouping() != nTextGrouping) )
1789 : {
1790 0 : pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping );
1791 0 : bChanged = true;
1792 : }
1793 : }
1794 :
1795 0 : if (!bDoSetAnimateFormFirst&&bNeedDoSetAnimateForm)
1796 : {
1797 0 : pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1798 0 : bChanged = true;
1799 : }
1800 :
1801 0 : if( bHasTextGroupingAuto )
1802 : {
1803 0 : if( pTextGroup->getTextGroupingAuto() != fTextGroupingAuto )
1804 : {
1805 0 : pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto );
1806 0 : bChanged = true;
1807 : }
1808 : }
1809 :
1810 0 : if( bHasTextReverse )
1811 : {
1812 0 : if( pTextGroup->getTextReverse() != bTextReverse )
1813 : {
1814 0 : pEffectSequence->setTextReverse( pTextGroup, bTextReverse );
1815 0 : bChanged = true;
1816 : }
1817 : }
1818 0 : }
1819 : }
1820 :
1821 0 : if( bChanged )
1822 : {
1823 0 : mpMainSequence->rebuild();
1824 0 : updateControls();
1825 0 : mrBase.GetDocShell()->SetModified();
1826 0 : }
1827 0 : }
1828 :
1829 0 : void CustomAnimationPane::showOptions( sal_uInt16 nPage /* = 0 */ )
1830 : {
1831 0 : STLPropertySet* pSet = createSelectionSet();
1832 :
1833 0 : CustomAnimationDialog* pDlg = new CustomAnimationDialog( this, pSet, nPage );
1834 0 : if( pDlg->Execute() )
1835 : {
1836 0 : addUndo();
1837 0 : changeSelection( pDlg->getResultSet(), pSet );
1838 0 : updateControls();
1839 : }
1840 :
1841 0 : delete pDlg;
1842 0 : }
1843 :
1844 0 : void CustomAnimationPane::onChangeCurrentPage()
1845 : {
1846 0 : if( mxView.is() ) try
1847 : {
1848 0 : Reference< XDrawPage > xNewPage( mxView->getCurrentPage() );
1849 0 : if( xNewPage != mxCurrentPage )
1850 : {
1851 0 : mxCurrentPage = xNewPage;
1852 0 : SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
1853 0 : if( pPage )
1854 : {
1855 0 : mpMainSequence = pPage->getMainSequence();
1856 0 : mpCustomAnimationList->update( mpMainSequence );
1857 : }
1858 0 : updateControls();
1859 0 : }
1860 : }
1861 0 : catch( Exception& )
1862 : {
1863 : OSL_FAIL( "sd::CustomAnimationPane::onChangeCurrentPage(), exception caught!" );
1864 : }
1865 0 : }
1866 :
1867 0 : bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::list< sal_Int16 >& rParaList )
1868 : {
1869 0 : Reference< XTextRange > xSelectedText;
1870 0 : rSelection >>= xSelectedText;
1871 0 : if( xSelectedText.is() ) try
1872 : {
1873 0 : xShape.set( xSelectedText->getText(), UNO_QUERY_THROW );
1874 :
1875 0 : Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW );
1876 0 : Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW );
1877 0 : Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW );
1878 0 : Reference< XTextRange > xRange;
1879 0 : Reference< XTextRange > xStart( xSelectedText->getStart() );
1880 0 : Reference< XTextRange > xEnd( xSelectedText->getEnd() );
1881 :
1882 0 : if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 )
1883 : {
1884 0 : Reference< XTextRange > xTemp( xStart );
1885 0 : xStart = xEnd;
1886 0 : xEnd = xTemp;
1887 : }
1888 :
1889 0 : sal_Int16 nPara = 0;
1890 0 : while( xParaEnum->hasMoreElements() )
1891 : {
1892 0 : xParaEnum->nextElement() >>= xRange;
1893 :
1894 : // break if start of selection is prior to end of current paragraph
1895 0 : if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) )
1896 0 : break;
1897 :
1898 0 : nPara++;
1899 : }
1900 :
1901 0 : while( xRange.is() )
1902 : {
1903 0 : if( xRange.is() && !xRange->getString().isEmpty() )
1904 0 : rParaList.push_back( nPara );
1905 :
1906 : // break if end of selection is before or at end of current paragraph
1907 0 : if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 )
1908 0 : break;
1909 :
1910 0 : nPara++;
1911 :
1912 0 : if( xParaEnum->hasMoreElements() )
1913 0 : xParaEnum->nextElement() >>= xRange;
1914 : else
1915 0 : xRange.clear();
1916 : }
1917 :
1918 0 : return true;
1919 : }
1920 0 : catch( Exception& )
1921 : {
1922 : OSL_FAIL( "sd::CustomAnimationPane::getTextSelection(), exception caught!" );
1923 : }
1924 :
1925 0 : return false;
1926 : }
1927 :
1928 0 : void CustomAnimationPane::onChange( bool bCreate )
1929 : {
1930 0 : bool bHasText = true;
1931 :
1932 : // first create vector of targets for dialog preview
1933 0 : std::vector< Any > aTargets;
1934 0 : OUString sPresetId;
1935 0 : double fDuration = 2.0f;
1936 :
1937 0 : if( bCreate )
1938 : {
1939 : // gather shapes from the selection
1940 0 : Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
1941 0 : maViewSelection = xSel->getSelection();
1942 :
1943 0 : if( maViewSelection.getValueType() == ::getCppuType((const Reference< XShapes >*)0) )
1944 : {
1945 0 : Reference< XIndexAccess > xShapes;
1946 0 : maViewSelection >>= xShapes;
1947 :
1948 0 : sal_Int32 nCount = xShapes->getCount();
1949 : sal_Int32 nIndex;
1950 0 : for( nIndex = 0; nIndex < nCount; nIndex++ )
1951 : {
1952 0 : Any aTarget( xShapes->getByIndex( nIndex ) );
1953 0 : aTargets.push_back( aTarget );
1954 0 : if( bHasText )
1955 : {
1956 0 : Reference< XText > xText;
1957 0 : aTarget >>= xText;
1958 0 : if( !xText.is() || xText->getString().isEmpty() )
1959 0 : bHasText = false;
1960 : }
1961 0 : }
1962 : }
1963 0 : else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XShape >*)0) )
1964 : {
1965 0 : aTargets.push_back( maViewSelection );
1966 0 : Reference< XText > xText;
1967 0 : maViewSelection >>= xText;
1968 0 : if( !xText.is() || xText->getString().isEmpty() )
1969 0 : bHasText = false;
1970 : }
1971 0 : else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XTextCursor >*)0) )
1972 : {
1973 0 : Reference< XShape > xShape;
1974 0 : std::list< sal_Int16 > aParaList;
1975 0 : if( getTextSelection( maViewSelection, xShape, aParaList ) )
1976 : {
1977 0 : ParagraphTarget aParaTarget;
1978 0 : aParaTarget.Shape = xShape;
1979 :
1980 0 : std::list< sal_Int16 >::iterator aIter( aParaList.begin() );
1981 0 : for( ; aIter != aParaList.end(); ++aIter )
1982 : {
1983 0 : aParaTarget.Paragraph = (*aIter);
1984 0 : aTargets.push_back( makeAny( aParaTarget ) );
1985 0 : }
1986 0 : }
1987 : }
1988 : else
1989 : {
1990 : OSL_FAIL("sd::CustomAnimationPane::onChange(), unknown view selection!" );
1991 0 : return;
1992 0 : }
1993 : }
1994 : else
1995 : {
1996 : // get selected effect
1997 0 : EffectSequence::iterator aIter( maListSelection.begin() );
1998 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
1999 0 : while( aIter != aEnd )
2000 : {
2001 0 : if( !bHasText || !(*aIter)->hasText() )
2002 0 : bHasText = false;
2003 :
2004 0 : if( sPresetId.isEmpty() )
2005 : {
2006 0 : sPresetId = (*aIter)->getPresetId();
2007 0 : fDuration = (*aIter)->getDuration();
2008 : }
2009 :
2010 0 : aTargets.push_back( (*aIter++)->getTarget() );
2011 : }
2012 : }
2013 :
2014 0 : CustomAnimationCreateDialog* pDlg = new CustomAnimationCreateDialog( this, this, aTargets, bHasText, sPresetId, fDuration );
2015 0 : if( pDlg->Execute() )
2016 : {
2017 0 : addUndo();
2018 0 : fDuration = pDlg->getSelectedDuration();
2019 0 : CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset();
2020 0 : if( pDescriptor.get() )
2021 : {
2022 0 : if( bCreate )
2023 : {
2024 0 : mpCustomAnimationList->SelectAll( sal_False );
2025 :
2026 : // gather shapes from the selection
2027 0 : std::vector< Any >::iterator aIter( aTargets.begin() );
2028 0 : const std::vector< Any >::iterator aEnd( aTargets.end() );
2029 0 : bool bFirst = true;
2030 0 : for( ; aIter != aEnd; ++aIter )
2031 : {
2032 0 : CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration );
2033 :
2034 : // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
2035 0 : if( bHasText && (aTargets.size() == 1) )
2036 : {
2037 0 : Reference< XShape > xShape( (*aIter), UNO_QUERY );
2038 0 : if( xShape.is() && !hasVisibleShape( xShape ) )
2039 : {
2040 0 : mpMainSequence->createTextGroup( pCreated, 1, -1.0, sal_False, sal_False );
2041 0 : }
2042 : }
2043 :
2044 0 : if( bFirst )
2045 0 : bFirst = false;
2046 : else
2047 0 : pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );
2048 :
2049 0 : if( pCreated.get() )
2050 : {
2051 0 : mpCustomAnimationList->select( pCreated );
2052 : }
2053 0 : }
2054 : }
2055 : else
2056 : {
2057 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2058 :
2059 : // get selected effect
2060 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2061 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2062 0 : while( aIter != aEnd )
2063 : {
2064 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2065 :
2066 0 : EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
2067 0 : if( !pEffectSequence )
2068 0 : pEffectSequence = mpMainSequence.get();
2069 :
2070 0 : pEffectSequence->replace( pEffect, pDescriptor, fDuration );
2071 0 : }
2072 : }
2073 : }
2074 : else
2075 : {
2076 0 : PathKind eKind = pDlg->getCreatePathKind();
2077 0 : if( eKind != NONE )
2078 0 : createPath( eKind, aTargets, fDuration );
2079 : }
2080 0 : mrBase.GetDocShell()->SetModified();
2081 : }
2082 :
2083 0 : delete pDlg;
2084 :
2085 0 : updateControls();
2086 :
2087 : // stop running preview from dialog
2088 0 : SlideShow::Stop( mrBase );
2089 : }
2090 :
2091 0 : void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration)
2092 : {
2093 0 : sal_uInt16 nSID = 0;
2094 :
2095 0 : switch( eKind )
2096 : {
2097 0 : case CURVE: nSID = SID_DRAW_BEZIER_NOFILL; break;
2098 0 : case POLYGON: nSID = SID_DRAW_POLYGON_NOFILL; break;
2099 0 : case FREEFORM: nSID = SID_DRAW_FREELINE_NOFILL; break;
2100 0 : default: break;
2101 : }
2102 :
2103 0 : if( nSID )
2104 : {
2105 : DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2106 0 : FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2107 :
2108 0 : if( pViewShell )
2109 : {
2110 0 : DrawView* pView = pViewShell->GetDrawView();
2111 0 : if( pView )
2112 0 : pView->UnmarkAllObj();
2113 :
2114 0 : std::vector< Any > aTargets( 1, Any( fDuration ) );
2115 0 : aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() );
2116 0 : Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) );
2117 0 : const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) );
2118 0 : pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSID, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
2119 : }
2120 : }
2121 0 : }
2122 :
2123 0 : void CustomAnimationPane::onRemove()
2124 : {
2125 0 : if( !maListSelection.empty() )
2126 : {
2127 0 : addUndo();
2128 :
2129 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2130 :
2131 0 : EffectSequence aList( maListSelection );
2132 :
2133 0 : EffectSequence::iterator aIter( aList.begin() );
2134 0 : const EffectSequence::iterator aEnd( aList.end() );
2135 0 : while( aIter != aEnd )
2136 : {
2137 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2138 0 : if( pEffect->getEffectSequence() )
2139 0 : pEffect->getEffectSequence()->remove( pEffect );
2140 0 : }
2141 :
2142 0 : maListSelection.clear();
2143 0 : mrBase.GetDocShell()->SetModified();
2144 : }
2145 0 : }
2146 :
2147 0 : void CustomAnimationPane::remove( CustomAnimationEffectPtr& pEffect )
2148 : {
2149 0 : if( pEffect->getEffectSequence() )
2150 : {
2151 0 : addUndo();
2152 0 : pEffect->getEffectSequence()->remove( pEffect );
2153 0 : mrBase.GetDocShell()->SetModified();
2154 : }
2155 0 : }
2156 :
2157 0 : void CustomAnimationPane::onChangeStart()
2158 : {
2159 0 : if( mpLBStart->GetSelectEntryCount() == 1 )
2160 : {
2161 : sal_Int16 nNodeType;
2162 0 : sal_uInt16 nPos= mpLBStart->GetSelectEntryPos();
2163 0 : switch( nPos )
2164 : {
2165 0 : case 0: nNodeType = EffectNodeType::ON_CLICK; break;
2166 0 : case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break;
2167 0 : case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break;
2168 : default:
2169 0 : return;
2170 : }
2171 :
2172 0 : onChangeStart( nNodeType );
2173 : }
2174 : }
2175 :
2176 0 : void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType )
2177 : {
2178 0 : addUndo();
2179 :
2180 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2181 :
2182 0 : bool bNeedRebuild = false;
2183 :
2184 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2185 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2186 0 : while( aIter != aEnd )
2187 : {
2188 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2189 0 : if( pEffect->getNodeType() != nNodeType )
2190 : {
2191 0 : pEffect->setNodeType( nNodeType );
2192 0 : bNeedRebuild = true;
2193 : }
2194 0 : }
2195 :
2196 0 : if( bNeedRebuild )
2197 : {
2198 0 : mpMainSequence->rebuild();
2199 0 : updateControls();
2200 0 : mrBase.GetDocShell()->SetModified();
2201 0 : }
2202 0 : }
2203 :
2204 0 : void CustomAnimationPane::onChangeProperty()
2205 : {
2206 0 : if( mpLBProperty->getSubControl() )
2207 : {
2208 0 : addUndo();
2209 :
2210 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2211 :
2212 0 : const Any aValue( mpLBProperty->getSubControl()->getValue() );
2213 :
2214 0 : bool bNeedUpdate = false;
2215 :
2216 : // change selected effect
2217 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2218 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2219 0 : while( aIter != aEnd )
2220 : {
2221 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2222 :
2223 0 : if( setProperty1Value( mnPropertyType, pEffect, aValue ) )
2224 0 : bNeedUpdate = true;
2225 0 : }
2226 :
2227 0 : if( bNeedUpdate )
2228 : {
2229 0 : mpMainSequence->rebuild();
2230 0 : updateControls();
2231 0 : mrBase.GetDocShell()->SetModified();
2232 : }
2233 :
2234 0 : onPreview( false );
2235 : }
2236 0 : }
2237 :
2238 0 : void CustomAnimationPane::onChangeSpeed()
2239 : {
2240 0 : if( mpCBSpeed->GetSelectEntryCount() == 1 )
2241 : {
2242 0 : addUndo();
2243 :
2244 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2245 :
2246 : double fDuration;
2247 :
2248 0 : sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos();
2249 :
2250 0 : switch( nPos )
2251 : {
2252 0 : case 0: fDuration = 5.0; break;
2253 0 : case 1: fDuration = 3.0; break;
2254 0 : case 2: fDuration = 2.0; break;
2255 0 : case 3: fDuration = 1.0; break;
2256 0 : case 4: fDuration = 0.5; break;
2257 : default:
2258 0 : return;
2259 : }
2260 :
2261 : // change selected effect
2262 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2263 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2264 0 : while( aIter != aEnd )
2265 : {
2266 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2267 0 : pEffect->setDuration( fDuration );
2268 0 : }
2269 :
2270 0 : mpMainSequence->rebuild();
2271 0 : updateControls();
2272 0 : mrBase.GetDocShell()->SetModified();
2273 :
2274 0 : onPreview( false );
2275 : }
2276 : }
2277 :
2278 : /// this link is called when the property box is modified by the user
2279 0 : IMPL_LINK_NOARG(CustomAnimationPane, implPropertyHdl)
2280 : {
2281 0 : onChangeProperty();
2282 0 : return 0;
2283 : }
2284 :
2285 : /// this link is called when one of the controls is modified
2286 0 : IMPL_LINK( CustomAnimationPane, implControlHdl, Control*, pControl )
2287 : {
2288 0 : if( pControl == mpPBAddEffect )
2289 0 : onChange(true);
2290 0 : else if( pControl == mpPBChangeEffect )
2291 0 : onChange(false);
2292 0 : else if( pControl == mpPBRemoveEffect )
2293 0 : onRemove();
2294 0 : else if( pControl == mpLBStart )
2295 0 : onChangeStart();
2296 0 : else if( pControl == mpCBSpeed )
2297 0 : onChangeSpeed();
2298 0 : else if( pControl == mpPBPropertyMore )
2299 0 : showOptions();
2300 0 : else if( pControl == mpPBMoveUp )
2301 0 : moveSelection( true );
2302 0 : else if( pControl == mpPBMoveDown )
2303 0 : moveSelection( false );
2304 0 : else if( pControl == mpPBPlay )
2305 0 : onPreview( true );
2306 0 : else if( pControl == mpPBSlideShow )
2307 : {
2308 0 : mrBase.StartPresentation();
2309 : }
2310 0 : else if( pControl == mpCBAutoPreview )
2311 : {
2312 0 : SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
2313 0 : pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() ? sal_True : sal_False );
2314 : }
2315 :
2316 0 : updateControls();
2317 :
2318 0 : return 0;
2319 : }
2320 :
2321 0 : IMPL_LINK_NOARG(CustomAnimationPane, lateInitCallback)
2322 : {
2323 : // Call getPresets() to initiate the (expensive) construction of the
2324 : // presets list.
2325 0 : getPresets();
2326 :
2327 : // update selection and control states
2328 0 : onSelectionChanged();
2329 :
2330 0 : return 0;
2331 : }
2332 :
2333 0 : void CustomAnimationPane::moveSelection( bool bUp )
2334 : {
2335 0 : if( maListSelection.empty() )
2336 0 : return;
2337 :
2338 0 : EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence();
2339 0 : if( pSequence == 0 )
2340 0 : return;
2341 :
2342 0 : addUndo();
2343 :
2344 0 : bool bChanged = false;
2345 :
2346 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2347 0 : EffectSequence& rEffectSequence = pSequence->getSequence();
2348 :
2349 0 : if( bUp )
2350 : {
2351 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2352 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2353 :
2354 0 : while( aIter != aEnd )
2355 : {
2356 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2357 :
2358 0 : EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) );
2359 0 : if( aEffectPos != rEffectSequence.end() )
2360 : {
2361 0 : EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) );
2362 :
2363 0 : if( aInsertPos != rEffectSequence.begin() )
2364 : {
2365 0 : --aInsertPos;
2366 0 : while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2367 0 : --aInsertPos;
2368 :
2369 0 : rEffectSequence.insert( aInsertPos, pEffect );
2370 : }
2371 : else
2372 : {
2373 0 : rEffectSequence.push_front( pEffect );
2374 : }
2375 0 : bChanged = true;
2376 : }
2377 0 : }
2378 : }
2379 : else
2380 : {
2381 0 : EffectSequence::reverse_iterator aIter( maListSelection.rbegin() );
2382 0 : const EffectSequence::reverse_iterator aEnd( maListSelection.rend() );
2383 :
2384 0 : while( aIter != aEnd )
2385 : {
2386 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2387 :
2388 0 : EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) );
2389 0 : if( aEffectPos != rEffectSequence.end() )
2390 : {
2391 0 : EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) );
2392 :
2393 0 : if( aInsertPos != rEffectSequence.end() )
2394 : {
2395 0 : ++aInsertPos;
2396 0 : while( (aInsertPos != rEffectSequence.end()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2397 0 : ++aInsertPos;
2398 :
2399 0 : rEffectSequence.insert( aInsertPos, pEffect );
2400 : }
2401 : else
2402 : {
2403 0 : rEffectSequence.push_back( pEffect );
2404 : }
2405 0 : bChanged = true;
2406 : }
2407 0 : }
2408 : }
2409 :
2410 0 : if( bChanged )
2411 : {
2412 0 : mpMainSequence->rebuild();
2413 0 : updateControls();
2414 0 : mrBase.GetDocShell()->SetModified();
2415 0 : }
2416 : }
2417 :
2418 0 : void CustomAnimationPane::onPreview( bool bForcePreview )
2419 : {
2420 0 : if( !bForcePreview && !mpCBAutoPreview->IsChecked() )
2421 0 : return;
2422 :
2423 0 : if( maListSelection.empty() )
2424 : {
2425 0 : rtl::Reference< MotionPathTag > xMotionPathTag;
2426 0 : MotionPathTagVector::iterator aIter;
2427 0 : for( aIter = maMotionPathTags.begin(); aIter != maMotionPathTags.end(); ++aIter )
2428 : {
2429 0 : if( (*aIter)->isSelected() )
2430 : {
2431 0 : xMotionPathTag = (*aIter);
2432 0 : break;
2433 : }
2434 : }
2435 :
2436 0 : if( xMotionPathTag.is() )
2437 : {
2438 0 : MainSequencePtr pSequence( new MainSequence() );
2439 0 : pSequence->append( xMotionPathTag->getEffect()->clone() );
2440 0 : preview( pSequence->getRootNode() );
2441 : }
2442 : else
2443 : {
2444 0 : Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY );
2445 0 : if( !xNodeSupplier.is() )
2446 0 : return;
2447 :
2448 0 : preview( xNodeSupplier->getAnimationNode() );
2449 0 : }
2450 : }
2451 : else
2452 : {
2453 0 : MainSequencePtr pSequence( new MainSequence() );
2454 :
2455 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2456 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2457 :
2458 0 : while( aIter != aEnd )
2459 : {
2460 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2461 0 : pSequence->append( pEffect->clone() );
2462 0 : }
2463 :
2464 0 : preview( pSequence->getRootNode() );
2465 : }
2466 : }
2467 :
2468 0 : void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode )
2469 : {
2470 0 : Reference< XParallelTimeContainer > xRoot = ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() );
2471 0 : Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
2472 0 : aUserData[0].Name = "node-type";
2473 0 : aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT;
2474 0 : xRoot->setUserData( aUserData );
2475 0 : xRoot->appendChild( xAnimationNode );
2476 :
2477 0 : SlideShow::StartPreview( mrBase, mxCurrentPage, xRoot );
2478 0 : }
2479 :
2480 :
2481 : // ICustomAnimationListController
2482 0 : void CustomAnimationPane::onSelect()
2483 : {
2484 0 : maListSelection = mpCustomAnimationList->getSelection();
2485 0 : updateControls();
2486 0 : markShapesFromSelectedEffects();
2487 0 : }
2488 :
2489 :
2490 :
2491 :
2492 0 : const CustomAnimationPresets& CustomAnimationPane::getPresets (void)
2493 : {
2494 0 : if (mpCustomAnimationPresets == NULL)
2495 0 : mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets();
2496 0 : return *mpCustomAnimationPresets;
2497 : }
2498 :
2499 :
2500 :
2501 0 : void CustomAnimationPane::markShapesFromSelectedEffects()
2502 : {
2503 0 : if( !maSelectionLock.isLocked() )
2504 : {
2505 0 : ScopeLockGuard aGuard( maSelectionLock );
2506 : DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2507 0 : FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2508 0 : DrawView* pView = pViewShell ? pViewShell->GetDrawView() : NULL;
2509 :
2510 0 : if( pView )
2511 : {
2512 0 : pView->UnmarkAllObj();
2513 0 : EffectSequence::iterator aIter( maListSelection.begin() );
2514 0 : const EffectSequence::iterator aEnd( maListSelection.end() );
2515 0 : while( aIter != aEnd )
2516 : {
2517 0 : CustomAnimationEffectPtr pEffect = (*aIter++);
2518 :
2519 0 : Reference< XShape > xShape( pEffect->getTargetShape() );
2520 0 : SdrObject* pObj = GetSdrObjectFromXShape( xShape );
2521 0 : if( pObj )
2522 0 : pView->MarkObj(pObj, pView->GetSdrPageView(), sal_False, sal_False);
2523 0 : }
2524 0 : }
2525 : }
2526 0 : }
2527 :
2528 :
2529 0 : void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag )
2530 : {
2531 0 : MainSequenceRebuildGuard aGuard( mpMainSequence );
2532 0 : if( xTag.is() )
2533 : {
2534 0 : SdrPathObj* pPathObj = xTag->getPathObj();
2535 0 : CustomAnimationEffectPtr pEffect = xTag->getEffect();
2536 0 : if( (pPathObj != 0) && pEffect.get() != 0 )
2537 : {
2538 0 : ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
2539 0 : if( pManager )
2540 : {
2541 0 : SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
2542 0 : if( pPage )
2543 0 : pManager->AddUndoAction( new UndoAnimationPath( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) );
2544 : }
2545 :
2546 0 : pEffect->updatePathFromSdrPathObj( *pPathObj );
2547 0 : }
2548 0 : }
2549 0 : }
2550 :
2551 : // ====================================================================
2552 :
2553 0 : ::Window * createCustomAnimationPanel( ::Window* pParent, ViewShellBase& rBase )
2554 : {
2555 0 : DialogListBox* pWindow = 0;
2556 :
2557 0 : DrawDocShell* pDocSh = rBase.GetDocShell();
2558 0 : if( pDocSh )
2559 : {
2560 0 : pWindow = new DialogListBox( pParent, WB_CLIPCHILDREN|WB_TABSTOP|WB_AUTOHSCROLL );
2561 0 : const Size aMinSize( pWindow->LogicToPixel( Size( 80, 256 ), MAP_APPFONT ) );
2562 0 : pWindow->SetSizePixel(aMinSize);
2563 0 : pWindow->SetBackground(Wallpaper(Color(COL_BLUE)));
2564 :
2565 0 : ::Window* pPaneWindow = new CustomAnimationPane( pWindow, rBase, aMinSize );
2566 0 : pWindow->SetChildWindow( pPaneWindow, aMinSize );
2567 0 : pWindow->SetText( pPaneWindow->GetText() );
2568 : }
2569 :
2570 0 : return pWindow;
2571 : }
2572 :
2573 :
2574 :
2575 :
2576 0 : sal_Int32 getCustomAnimationPanelMinimumHeight (::Window* pDialog)
2577 : {
2578 0 : if (pDialog != NULL)
2579 0 : return pDialog->LogicToPixel(Size( 80, 256 ), MAP_APPFONT).Height();
2580 : else
2581 0 : return 0;
2582 : }
2583 :
2584 33 : }
2585 :
2586 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|