6626367f86
2005/01/04 12:15:36 cl 1.2.38.1: #i38950# fixed null pointer access in ::update()
1081 lines
34 KiB
C++
1081 lines
34 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: CustomAnimationList.cxx,v $
|
|
*
|
|
* $Revision: 1.3 $
|
|
*
|
|
* last change: $Author: kz $ $Date: 2005-01-21 18:18:28 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (the "License"); You may not use this file
|
|
* except in compliance with the License. You may obtain a copy of the
|
|
* License at http://www.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
|
|
#include <com/sun/star/drawing/XShapes.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_PRESENTATION_SHAPEANIMATIONSUBTYPE_HPP_
|
|
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_PRESENTATION_EFFECTNODETYPE_HPP_
|
|
#include <com/sun/star/presentation/EffectNodeType.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_PRESENTATION_PARAGRAPHTARGET_HPP_
|
|
#include <com/sun/star/presentation/ParagraphTarget.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
|
|
#include <com/sun/star/container/XEnumerationAccess.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_ANIMATIONS_XITERATECONTAINER_HPP_
|
|
#include <com/sun/star/animations/XIterateContainer.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_PRESENTATION_EFFECTPRESETCLASS_HPP_
|
|
#include <com/sun/star/presentation/EffectPresetClass.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_PRESENTATION_EFFECTCOMMANDS_HPP_
|
|
#include <com/sun/star/presentation/EffectCommands.hpp>
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_TEXT_XTEXTRANGE_HPP_
|
|
#include <com/sun/star/text/XTextRange.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
|
|
#include <com/sun/star/drawing/XDrawPage.hpp>
|
|
#endif
|
|
|
|
#ifndef _SVX_ACCESSIBILITY_SHAPE_TYPE_HANDLER_HXX
|
|
#include <svx/ShapeTypeHandler.hxx>
|
|
#endif
|
|
|
|
#ifndef _SD_CUSTOMANIMATIONLIST_HXX
|
|
#include "CustomAnimationList.hxx"
|
|
#endif
|
|
#ifndef _SD_CUSTOMANIMATIONPANE_HRC
|
|
#include "CustomAnimationPane.hrc"
|
|
#endif
|
|
#ifndef _SD_CUSTOMANIMATION_HRC
|
|
#include "CustomAnimation.hrc"
|
|
#endif
|
|
#ifndef _SD_CUSTOMANIMATIONPRESET_HXX
|
|
#include "CustomAnimationPreset.hxx"
|
|
#endif
|
|
|
|
#ifndef _SVTREELIST_HXX
|
|
#include <svtools/treelist.hxx>
|
|
#endif
|
|
|
|
#ifndef _SV_SVAPP_HXX
|
|
#include <vcl/svapp.hxx>
|
|
#endif
|
|
|
|
#ifndef SD_RESID_HXX
|
|
#include "sdresid.hxx"
|
|
#endif
|
|
|
|
#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();
|
|
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;
|
|
CustomAnimationEffectPtr mpEffect;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
CustomAnimationListEntryItem::CustomAnimationListEntryItem( SvLBoxEntry* pEntry, USHORT nFlags, OUString aDescription, CustomAnimationEffectPtr pEffect, CustomAnimationList* pParent )
|
|
: SvLBoxString( pEntry, nFlags, aDescription ), mpParent( pParent ), mpEffect(pEffect), maDescription( aDescription )
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
CustomAnimationListEntryItem::~CustomAnimationListEntryItem()
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
USHORT CustomAnimationListEntryItem::IsA()
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
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 nFlags, 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* pSource )
|
|
{
|
|
}
|
|
|
|
// ====================================================================
|
|
|
|
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 -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 nFlags, SvLBoxEntry* pEntry )
|
|
{
|
|
SvViewDataItem* pViewData = mpParent->GetViewDataItem( pEntry, this );
|
|
|
|
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* pSource )
|
|
{
|
|
}
|
|
|
|
// ====================================================================
|
|
|
|
CustomAnimationList::CustomAnimationList( ::Window* pParent, const ResId& rResId, ICustomAnimationListController* pController )
|
|
: SvTreeListBox( pParent, rResId ), mpLastParentEntry(0),
|
|
mpController( pController )
|
|
{
|
|
SetWindowBits( WinBits( 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 ); break;
|
|
case KEY_INSERT: mpController->onContextMenu( CM_CREATE ); break;
|
|
case KEY_SPACE:
|
|
{
|
|
const Point aPos;
|
|
const CommandEvent aCEvt( aPos, COMMAND_CONTEXTMENU );
|
|
Command( aCEvt );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
::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 ));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
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()
|
|
{
|
|
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( 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 ));
|
|
}
|
|
}
|
|
|
|
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< XShape > xShape;
|
|
Reference< XIndexAccess > xShapes;
|
|
aSelection >>= xShapes;
|
|
if( xShapes.is() )
|
|
{
|
|
sal_Int32 nCount = xShapes->getCount();
|
|
sal_Int32 nIndex;
|
|
for( nIndex = 0; nIndex < nCount; nIndex++ )
|
|
{
|
|
xShapes->getByIndex( nIndex ) >>= xShape;
|
|
selectShape( this, xShape );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aSelection >>= xShape;
|
|
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 pEffect( pChild->getEffect() );
|
|
if( pEffect.get() )
|
|
aSelection.push_back( pEffect );
|
|
}
|
|
|
|
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;
|
|
CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(FirstSelected());
|
|
while( pEntry )
|
|
{
|
|
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* >(Next( 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 );
|
|
|
|
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 )
|
|
{
|
|
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 );
|
|
}
|
|
}
|
|
|
|
}
|