summaryrefslogtreecommitdiff
path: root/sd/source/ui/animations/CustomAnimationList.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/animations/CustomAnimationList.cxx')
-rwxr-xr-xsd/source/ui/animations/CustomAnimationList.cxx1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/sd/source/ui/animations/CustomAnimationList.cxx b/sd/source/ui/animations/CustomAnimationList.cxx
new file mode 100755
index 000000000000..8dbb9fd95c41
--- /dev/null
+++ b/sd/source/ui/animations/CustomAnimationList.cxx
@@ -0,0 +1,1018 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
+#include <com/sun/star/presentation/EffectNodeType.hpp>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/animations/XIterateContainer.hpp>
+#include <com/sun/star/presentation/EffectPresetClass.hpp>
+#include <com/sun/star/presentation/EffectCommands.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <svx/ShapeTypeHandler.hxx>
+#include "CustomAnimationList.hxx"
+#ifndef _SD_CUSTOMANIMATIONPANE_HRC
+#include "CustomAnimationPane.hrc"
+#endif
+#ifndef _SD_CUSTOMANIMATION_HRC
+#include "CustomAnimation.hrc"
+#endif
+#include "CustomAnimationPreset.hxx"
+#include <svtools/treelist.hxx>
+#include <vcl/svapp.hxx>
+#include "sdresid.hxx"
+
+#include "res_bmp.hrc"
+#include "glob.hrc"
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::animations;
+using namespace ::com::sun::star::presentation;
+
+using ::rtl::OUString;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::text::XTextRange;
+using ::com::sun::star::drawing::XShape;
+using ::com::sun::star::drawing::XShapes;
+using ::com::sun::star::drawing::XDrawPage;
+using ::com::sun::star::container::XChild;
+using ::com::sun::star::container::XIndexAccess;
+using ::com::sun::star::container::XEnumerationAccess;
+using ::com::sun::star::container::XEnumeration;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XPropertySetInfo;
+using ::accessibility::ShapeTypeHandler;
+
+namespace sd {
+
+// go recursivly through all shapes in the given XShapes collection and return true as soon as the
+// given shape is found. nIndex is incremented for each shape with the same shape type as the given
+// shape is found until the given shape is found.
+static bool getShapeIndex( const Reference< XShapes >& xShapes, const Reference< XShape >& xShape, sal_Int32& nIndex )
+{
+ const sal_Int32 nCount = xShapes->getCount();
+ sal_Int32 n;
+ for( n = 0; n < nCount; n++ )
+ {
+ Reference< XShape > xChild;
+ xShapes->getByIndex( n ) >>= xChild;
+ if( xChild == xShape )
+ return true;
+
+ if( xChild->getShapeType() == xShape->getShapeType() )
+ nIndex++;
+
+ Reference< XShapes > xChildContainer( xChild, UNO_QUERY );
+ if( xChildContainer.is() )
+ {
+ if( getShapeIndex( xChildContainer, xShape, nIndex ) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// returns the index of the shape type from the given shape
+static sal_Int32 getShapeIndex( const Reference< XShape >& xShape )
+{
+ Reference< XChild > xChild( xShape, UNO_QUERY );
+ Reference< XShapes > xPage;
+
+ while( xChild.is() && !xPage.is() )
+ {
+ Reference< XInterface > x( xChild->getParent() );
+ xChild = Reference< XChild >::query( x );
+ Reference< XDrawPage > xTestPage( x, UNO_QUERY );
+ if( xTestPage.is() )
+ xPage = Reference< XShapes >::query( x );
+ }
+
+ sal_Int32 nIndex = 1;
+
+ if( xPage.is() && getShapeIndex( xPage, xShape, nIndex ) )
+ return nIndex;
+ else
+ return -1;
+}
+
+OUString getShapeDescription( const Reference< XShape >& xShape, bool bWithText = true )
+{
+ OUString aDescription;
+ Reference< XPropertySet > xSet( xShape, UNO_QUERY );
+ if( xSet.is() )
+ {
+ Reference< XPropertySetInfo > xInfo( xSet->getPropertySetInfo() );
+ const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UINameSingular") );
+ if( xInfo->hasPropertyByName( aPropName ) )
+ xSet->getPropertyValue( aPropName ) >>= aDescription;
+ }
+
+ aDescription += OUString( RTL_CONSTASCII_USTRINGPARAM(" "));
+ aDescription += OUString::valueOf( getShapeIndex( xShape ) );
+
+ if( bWithText )
+ {
+ Reference< XTextRange > xText( xShape, UNO_QUERY );
+ if( xText.is() )
+ {
+ OUString aText( xText->getString() );
+ if( aText.getLength() )
+ {
+ aDescription += OUString(RTL_CONSTASCII_USTRINGPARAM(": "));
+
+ aText = aText.replace( (sal_Unicode)'\n', (sal_Unicode)' ' );
+ aText = aText.replace( (sal_Unicode)'\r', (sal_Unicode)' ' );
+
+ aDescription += aText;
+ }
+ }
+ }
+ return aDescription;
+}
+
+static OUString getDescription( const Any& rTarget, bool bWithText = true )
+{
+ OUString aDescription;
+
+ if( rTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) )
+ {
+ ParagraphTarget aParaTarget;
+ rTarget >>= aParaTarget;
+
+ Reference< XEnumerationAccess > xText( aParaTarget.Shape, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW );
+ sal_Int32 nPara = aParaTarget.Paragraph;
+
+ while( xEnumeration->hasMoreElements() && nPara )
+ {
+ xEnumeration->nextElement();
+ nPara--;
+ }
+
+ DBG_ASSERT( xEnumeration->hasMoreElements(), "sd::CustomAnimationEffect::prepareText(), paragraph out of range!" );
+
+ if( xEnumeration->hasMoreElements() )
+ {
+ Reference< XTextRange > xParagraph;
+ xEnumeration->nextElement() >>= xParagraph;
+
+ if( xParagraph.is() )
+ aDescription = xParagraph->getString();
+ }
+ }
+ else
+ {
+ Reference< XShape > xShape;
+ rTarget >>= xShape;
+ if( xShape.is() )
+ aDescription = getShapeDescription( xShape, bWithText );
+ }
+
+ return aDescription;
+}
+
+// ====================================================================
+
+class CustomAnimationListEntryItem : public SvLBoxString
+{
+public:
+ CustomAnimationListEntryItem( SvLBoxEntry*,USHORT nFlags, OUString aDescription, CustomAnimationEffectPtr pEffect, CustomAnimationList* pParent );
+ virtual ~CustomAnimationListEntryItem();
+ void InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );
+ void Paint( const Point&, SvLBox& rDev, USHORT nFlags,SvLBoxEntry* );
+ SvLBoxItem* Create() const;
+ void Clone( SvLBoxItem* pSource );
+
+private:
+ CustomAnimationList* mpParent;
+ OUString maDescription;
+ CustomAnimationEffectPtr mpEffect;
+};
+
+// --------------------------------------------------------------------
+
+CustomAnimationListEntryItem::CustomAnimationListEntryItem( SvLBoxEntry* pEntry, USHORT nFlags, OUString aDescription, CustomAnimationEffectPtr pEffect, CustomAnimationList* pParent )
+: SvLBoxString( pEntry, nFlags, aDescription )
+, mpParent( pParent )
+, maDescription( aDescription )
+, mpEffect(pEffect)
+{
+}
+
+// --------------------------------------------------------------------
+
+CustomAnimationListEntryItem::~CustomAnimationListEntryItem()
+{
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationListEntryItem::InitViewData( SvLBox* pView, SvLBoxEntry* pEntry, SvViewDataItem* pViewData )
+{
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+
+ Size aSize(pView->GetTextWidth( maDescription ) + 2 * 19, pView->GetTextHeight() );
+ if( aSize.Height() < 19 )
+ aSize.Height() = 19;
+ pViewData->aSize = aSize;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationListEntryItem::Paint( const Point& rPos, SvLBox& rDev, USHORT, SvLBoxEntry* pEntry )
+{
+ const bool bHighContrast = Application::GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ SvViewDataItem* pViewData = mpParent->GetViewDataItem( pEntry, this );
+
+ Point aPos( rPos );
+ Size aSize( pViewData->aSize );
+
+ sal_Int16 nNodeType = mpEffect->getNodeType();
+ if( nNodeType == EffectNodeType::ON_CLICK )
+ {
+ rDev.DrawImage( aPos, mpParent->getImage( IMG_CUSTOMANIMATION_ON_CLICK, bHighContrast ) );
+ }
+ else if( nNodeType == EffectNodeType::AFTER_PREVIOUS )
+ {
+ rDev.DrawImage( aPos, mpParent->getImage( IMG_CUSTOMANIMATION_AFTER_PREVIOUS, bHighContrast ) );
+ }
+
+ aPos.X() += 19;
+
+ USHORT nImage;
+ switch( mpEffect->getPresetClass() )
+ {
+ case EffectPresetClass::ENTRANCE: nImage = IMG_CUSTOMANIMATION_ENTRANCE_EFFECT; break;
+ case EffectPresetClass::EXIT: nImage = IMG_CUSTOMANIMATION_EXIT_EFFECT; break;
+ case EffectPresetClass::EMPHASIS: nImage = IMG_CUSTOMANIMATION_EMPHASIS_EFFECT; break;
+ case EffectPresetClass::MOTIONPATH: nImage = IMG_CUSTOMANIMATION_MOTION_PATH; break;
+ case EffectPresetClass::OLEACTION: nImage = IMG_CUSTOMANIMATION_OLE; break;
+ case EffectPresetClass::MEDIACALL:
+ switch( mpEffect->getCommand() )
+ {
+ case EffectCommands::TOGGLEPAUSE: nImage = IMG_CUSTOMANIMATION_MEDIA_PAUSE; break;
+ case EffectCommands::STOP: nImage = IMG_CUSTOMANIMATION_MEDIA_STOP; break;
+ case EffectCommands::PLAY:
+ default: nImage = IMG_CUSTOMANIMATION_MEDIA_PLAY; break;
+ }
+ break;
+ default: nImage = 0xffff;
+ }
+
+ if( nImage != 0xffff )
+ {
+ const Image& rImage = mpParent->getImage( nImage, bHighContrast );
+ Point aImagePos( aPos );
+ aImagePos.Y() += ( aSize.Height() - rImage.GetSizePixel().Height() ) >> 1;
+ rDev.DrawImage( aImagePos, rImage );
+ }
+
+ aPos.X() += 19;
+ aPos.Y() += ( aSize.Height() - rDev.GetTextHeight()) >> 1;
+
+ rDev.DrawText( aPos, rDev.GetEllipsisString( maDescription, rDev.GetOutputSizePixel().Width() - aPos.X() ) );
+}
+
+// --------------------------------------------------------------------
+
+SvLBoxItem* CustomAnimationListEntryItem::Create() const
+{
+ return NULL;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationListEntryItem::Clone( SvLBoxItem* )
+{
+}
+
+// ====================================================================
+
+class CustomAnimationListEntry : public SvLBoxEntry
+{
+public:
+ CustomAnimationListEntry();
+ CustomAnimationListEntry( CustomAnimationEffectPtr pEffect );
+ virtual ~CustomAnimationListEntry();
+
+ CustomAnimationEffectPtr getEffect() const { return mpEffect; }
+
+private:
+ CustomAnimationEffectPtr mpEffect;
+};
+
+// --------------------------------------------------------------------
+
+CustomAnimationListEntry::CustomAnimationListEntry()
+{
+}
+
+// --------------------------------------------------------------------
+
+CustomAnimationListEntry::CustomAnimationListEntry( CustomAnimationEffectPtr pEffect )
+: mpEffect( pEffect )
+{
+}
+
+// --------------------------------------------------------------------
+
+CustomAnimationListEntry::~CustomAnimationListEntry()
+{
+}
+
+// ====================================================================
+
+class CustomAnimationTriggerEntryItem : public SvLBoxString
+{
+public:
+ CustomAnimationTriggerEntryItem( SvLBoxEntry*,USHORT nFlags, OUString aDescription, CustomAnimationList* pParent );
+ virtual ~CustomAnimationTriggerEntryItem();
+ virtual USHORT IsA();
+ void InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );
+ void Paint( const Point&, SvLBox& rDev, USHORT nFlags,SvLBoxEntry* );
+ SvLBoxItem* Create() const;
+ void Clone( SvLBoxItem* pSource );
+
+private:
+ CustomAnimationList* mpParent;
+ OUString maDescription;
+};
+
+// --------------------------------------------------------------------
+
+CustomAnimationTriggerEntryItem::CustomAnimationTriggerEntryItem( SvLBoxEntry* pEntry, USHORT nFlags, OUString aDescription, CustomAnimationList* pParent )
+: SvLBoxString( pEntry, nFlags, aDescription ), mpParent( pParent ), maDescription( aDescription )
+{
+}
+
+// --------------------------------------------------------------------
+
+CustomAnimationTriggerEntryItem::~CustomAnimationTriggerEntryItem()
+{
+}
+
+// --------------------------------------------------------------------
+
+USHORT CustomAnimationTriggerEntryItem::IsA()
+{
+ return (USHORT)-1;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationTriggerEntryItem::InitViewData( SvLBox* pView, SvLBoxEntry* pEntry, SvViewDataItem* pViewData )
+{
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+
+ Size aSize(pView->GetTextWidth( maDescription ) + 2 * 19, pView->GetTextHeight() );
+ if( aSize.Height() < 19 )
+ aSize.Height() = 19;
+ pViewData->aSize = aSize;
+
+/*
+ SvViewData* pViewData = pView->GetViewData( pEntry );
+ if( pViewData )
+ pViewData->SetSelectable(false);
+*/
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationTriggerEntryItem::Paint( const Point& rPos, SvLBox& rDev, USHORT, SvLBoxEntry* )
+{
+ Size aSize( rDev.GetOutputSizePixel().Width(), static_cast< SvTreeListBox* >(&rDev)->GetEntryHeight() );
+
+ Point aPos( 0, rPos.Y() );
+
+ Rectangle aOutRect( aPos, aSize );
+
+ // fill the background
+ Color aColor (rDev.GetSettings().GetStyleSettings().GetDialogColor());
+
+ rDev.Push();
+ rDev.SetFillColor (aColor);
+ rDev.SetLineColor ();
+ rDev.DrawRect(aOutRect);
+
+ // Erase the four corner pixels to make the rectangle appear rounded.
+ rDev.SetLineColor( rDev.GetSettings().GetStyleSettings().GetWindowColor());
+ rDev.DrawPixel( aOutRect.TopLeft());
+ rDev.DrawPixel( Point(aOutRect.Right(), aOutRect.Top()));
+ rDev.DrawPixel( Point(aOutRect.Left(), aOutRect.Bottom()));
+ rDev.DrawPixel( Point(aOutRect.Right(), aOutRect.Bottom()));
+
+ // draw the category title
+
+ int nVertBorder = (( aSize.Height() - rDev.GetTextHeight()) >> 1);
+ int nHorzBorder = rDev.LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width();
+
+ aOutRect.nLeft += nHorzBorder;
+ aOutRect.nRight -= nHorzBorder;
+ aOutRect.nTop += nVertBorder;
+ aOutRect.nBottom -= nVertBorder;
+
+ rDev.DrawText (aOutRect, rDev.GetEllipsisString( maDescription, aOutRect.GetWidth() ) );
+ rDev.Pop();
+}
+
+// --------------------------------------------------------------------
+
+SvLBoxItem* CustomAnimationTriggerEntryItem::Create() const
+{
+ return NULL;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationTriggerEntryItem::Clone( SvLBoxItem* )
+{
+}
+
+// ====================================================================
+
+CustomAnimationList::CustomAnimationList( ::Window* pParent, const ResId& rResId, ICustomAnimationListController* pController )
+: SvTreeListBox( pParent, rResId )
+, mbIgnorePaint( false )
+, mpController( pController )
+, mpLastParentEntry(0)
+{
+ SetStyle( GetStyle() | WB_TABSTOP | WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT );
+
+ EnableContextMenuHandling();
+ SetSelectionMode( MULTIPLE_SELECTION );
+ SetIndent(16);
+ SetNodeDefaultImages();
+}
+
+// --------------------------------------------------------------------
+
+const Image& CustomAnimationList::getImage( USHORT nId, bool bHighContrast )
+{
+ DBG_ASSERT( (nId >= IMG_CUSTOMANIMATION_ON_CLICK) && (nId <= IMG_CUSTOMANIMATION_MEDIA_STOP), "sd::CustomAnimationList::getImage(), illegal index!" );
+
+ if( bHighContrast )
+ nId += 1;
+
+ Image& rImage = maImages[nId - IMG_CUSTOMANIMATION_ON_CLICK];
+
+ // load on demand
+ if( rImage.GetSizePixel().Width() == 0 )
+ rImage = Image(SdResId( nId ) );
+
+ return rImage;
+}
+
+// --------------------------------------------------------------------
+
+CustomAnimationList::~CustomAnimationList()
+{
+ if( mpMainSequence.get() )
+ mpMainSequence->removeListener( this );
+
+ clear();
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::KeyInput( const KeyEvent& rKEvt )
+{
+ const int nKeyCode = rKEvt.GetKeyCode().GetCode();
+ switch( nKeyCode )
+ {
+ case KEY_DELETE: mpController->onContextMenu( CM_REMOVE ); return;
+ case KEY_INSERT: mpController->onContextMenu( CM_CREATE ); return;
+ case KEY_SPACE:
+ {
+ const Point aPos;
+ const CommandEvent aCEvt( aPos, COMMAND_CONTEXTMENU );
+ Command( aCEvt );
+ return;
+ }
+
+ }
+
+ ::SvTreeListBox::KeyInput( rKEvt );
+}
+
+// --------------------------------------------------------------------
+
+/** selects or deselects the given effect.
+ Selections of other effects are not changed */
+void CustomAnimationList::select( CustomAnimationEffectPtr pEffect, bool bSelect /* = true */ )
+{
+ CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(First());
+ while( pEntry )
+ {
+ if( pEntry->getEffect() == pEffect )
+ {
+ Select( pEntry, bSelect );
+ break;
+ }
+ pEntry = static_cast< CustomAnimationListEntry* >(Next( pEntry ));
+ }
+
+ if( !pEntry && bSelect )
+ {
+ append( pEffect );
+ select( pEffect );
+ }
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::clear()
+{
+ Clear();
+
+ mpLastParentEntry = 0;
+ mxLastTargetShape = 0;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::update( MainSequencePtr pMainSequence )
+{
+ if( mpMainSequence.get() )
+ mpMainSequence->removeListener( this );
+
+ mpMainSequence = pMainSequence;
+ update();
+
+ if( mpMainSequence.get() )
+ mpMainSequence->addListener( this );
+}
+
+// --------------------------------------------------------------------
+
+struct stl_append_effect_func : public std::unary_function<CustomAnimationEffectPtr, void>
+{
+ stl_append_effect_func( CustomAnimationList& rList ) : mrList( rList ) {}
+ void operator()(CustomAnimationEffectPtr pEffect);
+ CustomAnimationList& mrList;
+};
+
+void stl_append_effect_func::operator()(CustomAnimationEffectPtr pEffect)
+{
+ mrList.append( pEffect );
+}
+// --------------------------------------------------------------------
+
+void CustomAnimationList::update()
+{
+ mbIgnorePaint = true;
+
+ CustomAnimationListEntry* pEntry = 0;
+
+ std::list< CustomAnimationEffectPtr > aExpanded;
+ std::list< CustomAnimationEffectPtr > aSelected;
+
+ CustomAnimationEffectPtr pFirstVisibleEffect;
+
+ if( mpMainSequence.get() )
+ {
+ // save selection and expand states
+ pEntry = static_cast<CustomAnimationListEntry*>(FirstVisible());
+ if( pEntry )
+ pFirstVisibleEffect = pEntry->getEffect();
+
+ pEntry = static_cast<CustomAnimationListEntry*>(First());
+
+ while( pEntry )
+ {
+ CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+ if( pEffect.get() )
+ {
+ if( IsExpanded( pEntry ) )
+ aExpanded.push_back( pEffect );
+
+ if( IsSelected( pEntry ) )
+ aSelected.push_back( pEffect );
+ }
+
+ pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+ }
+ }
+
+ // rebuild list
+ clear();
+ if( mpMainSequence.get() )
+ {
+ std::for_each( mpMainSequence->getBegin(), mpMainSequence->getEnd(), stl_append_effect_func( *this ) );
+ mpLastParentEntry = 0;
+
+ const InteractiveSequenceList& rISL = mpMainSequence->getInteractiveSequenceList();
+
+ InteractiveSequenceList::const_iterator aIter( rISL.begin() );
+ const InteractiveSequenceList::const_iterator aEnd( rISL.end() );
+ while( aIter != aEnd )
+ {
+ InteractiveSequencePtr pIS( (*aIter++) );
+
+ Reference< XShape > xShape( pIS->getTriggerShape() );
+ if( xShape.is() )
+ {
+ SvLBoxEntry* pLBoxEntry = new CustomAnimationListEntry;
+ pLBoxEntry->AddItem( new SvLBoxContextBmp( pLBoxEntry, 0, Image(), Image(), 0));
+ OUString aDescription = String( SdResId( STR_CUSTOMANIMATION_TRIGGER ) );
+ aDescription += OUString( RTL_CONSTASCII_USTRINGPARAM(": ") );
+ aDescription += getShapeDescription( xShape, false );
+ pLBoxEntry->AddItem( new CustomAnimationTriggerEntryItem( pLBoxEntry, 0, aDescription, this ) );
+ Insert( pLBoxEntry );
+ SvViewData* pViewData = GetViewData( pLBoxEntry );
+ if( pViewData )
+ pViewData->SetSelectable(false);
+
+ std::for_each( pIS->getBegin(), pIS->getEnd(), stl_append_effect_func( *this ) );
+ mpLastParentEntry = 0;
+ }
+ }
+
+ // restore selection and expand states
+ pEntry = static_cast<CustomAnimationListEntry*>(First());
+
+ while( pEntry )
+ {
+ CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+ if( pEffect.get() )
+ {
+ if( std::find( aExpanded.begin(), aExpanded.end(), pEffect ) != aExpanded.end() )
+ Expand( pEntry );
+
+ if( std::find( aSelected.begin(), aSelected.end(), pEffect ) != aSelected.end() )
+ Select( pEntry );
+
+ if( pFirstVisibleEffect == pEffect )
+ MakeVisible( pEntry );
+ }
+
+ pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+ }
+ }
+
+ mbIgnorePaint = false;
+ Invalidate();
+}
+
+// --------------------------------------------------------------------
+
+/*
+void CustomAnimationList::update( CustomAnimationEffectPtr pEffect )
+{
+ SvLBoxEntry* pEntry = First();
+ while( pEntry )
+ {
+ if( static_cast< CustomAnimationEffectPtr * >( pEntry->GetUserData() )->get() == pEffect.get() )
+ {
+ CustomAnimationPresetsPtr pPresets = mpController->getPresets();
+ const CustomAnimationPresetPtr pPreset = pPresets->getEffectDescriptor( pEffect->getPresetId() );
+ if( pPreset.get() )
+ pEffect->setName( pPresets->getUINameForPresetId( pPreset->getPresetId() ) );
+ else
+ pEffect->setName( pEffect->getPresetId() );
+ break;
+ }
+ pEntry = Next( pEntry );
+ }
+
+ Invalidate();
+}
+*/
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::append( CustomAnimationEffectPtr pEffect )
+{
+ // create a ui description
+ OUString aDescription;
+
+ Any aTarget( pEffect->getTarget() );
+ if( aTarget.hasValue() ) try
+ {
+ aDescription = getDescription( aTarget, pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_BACKGROUND );
+
+ SvLBoxEntry* pParentEntry = 0;
+
+ Reference< XShape > xTargetShape( pEffect->getTargetShape() );
+ sal_Int32 nGroupId = pEffect->getGroupId();
+
+ // if this effect has the same target and group-id as the last root effect,
+ // the last root effect is also this effects parent
+ if( mpLastParentEntry && (nGroupId != -1) && (mxLastTargetShape == xTargetShape) && (mnLastGroupId == nGroupId) )
+ pParentEntry = mpLastParentEntry;
+
+ // create an entry for the effect
+ SvLBoxEntry* pEntry = new CustomAnimationListEntry( pEffect );
+
+ pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0));
+ pEntry->AddItem( new CustomAnimationListEntryItem( pEntry, 0, aDescription, pEffect, this ) );
+
+ if( pParentEntry )
+ {
+ // add a subentry
+ Insert( pEntry, pParentEntry );
+ }
+ else
+ {
+ // add a root entry
+ Insert( pEntry );
+
+ // and the new root entry becomes the possible next group header
+ mxLastTargetShape = xTargetShape;
+ mnLastGroupId = nGroupId;
+ mpLastParentEntry = pEntry;
+ }
+ }
+ catch( Exception& e )
+ {
+ (void)e;
+ DBG_ERROR("sd::CustomAnimationList::append(), exception catched!" );
+ }
+}
+
+// --------------------------------------------------------------------
+
+/*
+void CustomAnimationList::remove( CustomAnimationEffectPtr pEffect )
+{
+ SvLBoxEntry* pEntry = First();
+ while( pEntry )
+ {
+ if( static_cast< CustomAnimationEffectPtr * >( pEntry->GetUserData() )->get() == pEffect.get() )
+ {
+ GetModel()->Remove( pEntry );
+ if( pEntry == mpLastParentEntry )
+ {
+ mpLastParentEntry = 0;
+ mxLastTargetShape = 0;
+ }
+ break;
+ }
+ pEntry = Next( pEntry );
+ }
+
+ Invalidate();
+}
+*/
+
+// --------------------------------------------------------------------
+
+void selectShape( SvTreeListBox* pTreeList, Reference< XShape > xShape )
+{
+ CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->First());
+ while( pEntry )
+ {
+ CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+ if( pEffect.get() )
+ {
+ if( pEffect->getTarget() == xShape )
+ pTreeList->Select( pEntry );
+ }
+
+ pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->Next( pEntry ));
+ }
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::onSelectionChanged( Any aSelection )
+{
+ try
+ {
+ SelectAll(FALSE);
+
+ if( aSelection.hasValue() )
+ {
+ Reference< XIndexAccess > xShapes( aSelection, UNO_QUERY );
+ if( xShapes.is() )
+ {
+ sal_Int32 nCount = xShapes->getCount();
+ sal_Int32 nIndex;
+ for( nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ Reference< XShape > xShape( xShapes->getByIndex( nIndex ), UNO_QUERY );
+ if( xShape.is() )
+ selectShape( this, xShape );
+ }
+ }
+ else
+ {
+ Reference< XShape > xShape( aSelection, UNO_QUERY );
+ if( xShape.is() )
+ selectShape( this, xShape );
+ }
+ }
+
+ SelectHdl();
+ }
+ catch( Exception& )
+ {
+ DBG_ERROR( "sd::CustomAnimationList::onSelectionChanged(), Exception catched!" );
+ }
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::SelectHdl()
+{
+ SvTreeListBox::SelectHdl();
+ mpController->onSelect();
+}
+
+// --------------------------------------------------------------------
+
+bool CustomAnimationList::isExpanded( const CustomAnimationEffectPtr& pEffect ) const
+{
+ CustomAnimationListEntry* pEntry = static_cast<CustomAnimationListEntry*>(First());
+
+ while( pEntry )
+ {
+ if( pEntry->getEffect() == pEffect )
+ break;
+
+ pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+ }
+
+ if( pEntry )
+ pEntry = static_cast<CustomAnimationListEntry*>(GetParent( pEntry ));
+
+ return (pEntry == 0) || IsExpanded( pEntry );
+}
+
+// --------------------------------------------------------------------
+EffectSequence CustomAnimationList::getSelection() const
+{
+ EffectSequence aSelection;
+
+ CustomAnimationListEntry* pEntry = dynamic_cast< CustomAnimationListEntry* >(FirstSelected());
+ while( pEntry )
+ {
+ CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+ if( pEffect.get() )
+ aSelection.push_back( pEffect );
+
+ // if the selected effect is not expanded and has children
+ // we say that the children are automaticly selected
+ if( !IsExpanded( pEntry ) )
+ {
+ CustomAnimationListEntry* pChild = dynamic_cast< CustomAnimationListEntry* >( FirstChild( pEntry ) );
+ while( pChild )
+ {
+ if( !IsSelected( pChild ) )
+ {
+ CustomAnimationEffectPtr pChildEffect( pChild->getEffect() );
+ if( pChildEffect.get() )
+ aSelection.push_back( pChildEffect );
+ }
+
+ pChild = dynamic_cast< CustomAnimationListEntry* >( NextSibling( pChild ) );
+ }
+ }
+
+ pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry ));
+ }
+
+ return aSelection;
+}
+
+// --------------------------------------------------------------------
+
+BOOL CustomAnimationList::DoubleClickHdl()
+{
+ mpController->onDoubleClick();
+ return false;
+}
+
+// --------------------------------------------------------------------
+
+PopupMenu* CustomAnimationList::CreateContextMenu()
+{
+ PopupMenu* pMenu = new PopupMenu(SdResId( RID_EFFECT_CONTEXTMENU ));
+
+ sal_Int16 nNodeType = -1;
+ sal_Int16 nEntries = 0;
+
+ CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(FirstSelected());
+ while( pEntry )
+ {
+ nEntries++;
+ CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+ if( pEffect.get() )
+ {
+ if( nNodeType == -1 )
+ {
+ nNodeType = pEffect->getNodeType();
+ }
+ else
+ {
+ if( nNodeType != pEffect->getNodeType() )
+ {
+ nNodeType = -1;
+ break;
+ }
+ }
+ }
+
+ pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry ));
+ }
+
+ pMenu->CheckItem( CM_WITH_CLICK, nNodeType == EffectNodeType::ON_CLICK );
+ pMenu->CheckItem( CM_WITH_PREVIOUS, nNodeType == EffectNodeType::WITH_PREVIOUS );
+ pMenu->CheckItem( CM_AFTER_PREVIOUS, nNodeType == EffectNodeType::AFTER_PREVIOUS );
+ pMenu->EnableItem( CM_OPTIONS, nEntries == 1 );
+ pMenu->EnableItem( CM_DURATION, nEntries == 1 );
+
+ return pMenu;
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::ExcecuteContextMenuAction( USHORT nSelectedPopupEntry )
+{
+ mpController->onContextMenu( nSelectedPopupEntry );
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::SetTabs()
+{
+ SvTreeListBox::SetTabs();
+}
+
+// --------------------------------------------------------------------
+
+void CustomAnimationList::notify_change()
+{
+ update();
+ mpController->onSelect();
+}
+
+void CustomAnimationList::Paint( const Rectangle& rRect )
+{
+ if( mbIgnorePaint )
+ return;
+
+ SvTreeListBox::Paint( rRect );
+
+ // draw help text if list box is still empty
+ if( First() == 0 )
+ {
+ Color aOldColor( GetTextColor() );
+ SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
+ ::Point aOffset( LogicToPixel( Point( 6, 6 ), MAP_APPFONT ) );
+
+ Rectangle aRect( Point( 0,0 ), GetOutputSizePixel() );
+
+ aRect.Left() += aOffset.X();
+ aRect.Top() += aOffset.Y();
+ aRect.Right() -= aOffset.X();
+ aRect.Bottom() -= aOffset.Y();
+
+ DrawText( aRect, String( SdResId( STR_CUSTOMANIMATION_LIST_HELPTEXT ) ),
+ TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER );
+
+ SetTextColor( aOldColor );
+ }
+}
+
+}