diff options
Diffstat (limited to 'oox/source/vml/vmldrawing.cxx')
-rw-r--r-- | oox/source/vml/vmldrawing.cxx | 145 |
1 files changed, 130 insertions, 15 deletions
diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx index 61dfd4b6c362..ca2d362d11d8 100644 --- a/oox/source/vml/vmldrawing.cxx +++ b/oox/source/vml/vmldrawing.cxx @@ -27,28 +27,32 @@ ************************************************************************/ #include "oox/vml/vmldrawing.hxx" + +#include <algorithm> +#include <com/sun/star/drawing/XControlShape.hpp> #include <com/sun/star/drawing/XShapes.hpp> -#include "tokens.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> #include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/containerhelper.hxx" #include "oox/ole/axcontrol.hxx" #include "oox/vml/vmlshape.hxx" #include "oox/vml/vmlshapecontainer.hxx" -using ::rtl::OUString; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::awt::Rectangle; -using ::com::sun::star::awt::XControlModel; -using ::com::sun::star::drawing::XDrawPage; -using ::com::sun::star::drawing::XShape; -using ::com::sun::star::drawing::XShapes; -using ::oox::core::XmlFilterBase; - namespace oox { namespace vml { // ============================================================================ +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +using ::oox::core::XmlFilterBase; +using ::rtl::OUString; + +// ============================================================================ + namespace { /** Returns the textual representation of a numeric VML shape identifier. */ @@ -58,6 +62,13 @@ OUString lclGetShapeId( sal_Int32 nShapeId ) return CREATE_OUSTRING( "\0s" ) + OUString::valueOf( nShapeId ); } +/** Returns the numeric VML shape identifier from its textual representation. */ +sal_Int32 lclGetShapeId( const OUString& rShapeId ) +{ + // identifier consists of a literal NUL character, a lowercase 's', and the id + return ((rShapeId.getLength() >= 3) && (rShapeId[ 0 ] == '\0') && (rShapeId[ 1 ] == 's')) ? rShapeId.copy( 2 ).toInt32() : -1; +} + } // namespace // ============================================================================ @@ -107,6 +118,18 @@ Drawing::~Drawing() return *mxCtrlForm; } +void Drawing::registerBlockId( sal_Int32 nBlockId ) +{ + OSL_ENSURE( nBlockId > 0, "Drawing::registerBlockId - invalid block index" ); + if( nBlockId > 0 ) + { + // lower_bound() returns iterator pointing to element equal to nBlockId, if existing + BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId ); + if( (aIt == maBlockIds.end()) || (nBlockId != *aIt) ) + maBlockIds.insert( aIt, nBlockId ); + } +} + void Drawing::registerOleObject( const OleObjectInfo& rOleObject ) { OSL_ENSURE( rOleObject.maShapeId.getLength() > 0, "Drawing::registerOleObject - missing OLE object shape id" ); @@ -133,6 +156,47 @@ void Drawing::convertAndInsert() const mxShapes->convertAndInsert( xShapes ); } +sal_Int32 Drawing::getLocalShapeIndex( const OUString& rShapeId ) const +{ + sal_Int32 nShapeId = lclGetShapeId( rShapeId ); + if( nShapeId <= 0 ) return -1; + + /* Shapes in a drawing are counted per registered shape identifier blocks + as stored in the o:idmap element. The contents of this element have + been stored in our member maBlockIds. Each block represents 1024 shape + identifiers, starting with identifier 1 for the block #0. This means, + block #0 represents the identifiers 1-1024, block #1 represents the + identifiers 1025-2048, and so on. The local shape index has to be + calculated according to all blocks registered for this drawing. + + Example: + Registered for this drawing are blocks #1 and #3 (shape identifiers + 1025-2048 and 3073-4096). + Shape identifier 1025 -> local shape index 1. + Shape identifier 1026 -> local shape index 2. + ... + Shape identifier 2048 -> local shape index 1024. + Shape identifier 3073 -> local shape index 1025. + ... + Shape identifier 4096 -> local shape index 2048. + */ + + // get block id from shape id and find its index in the list of used blocks + sal_Int32 nBlockId = (nShapeId - 1) / 1024; + BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId ); + sal_Int32 nIndex = static_cast< sal_Int32 >( aIt - maBlockIds.begin() ); + + // block id not found in set -> register it now (value of nIndex remains valid) + if( (aIt == maBlockIds.end()) || (*aIt != nBlockId) ) + maBlockIds.insert( aIt, nBlockId ); + + // get one-based offset of shape id in its block + sal_Int32 nBlockOffset = (nShapeId - 1) % 1024 + 1; + + // calculate the local shape index + return 1024 * nIndex + nBlockOffset; +} + const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const { return ContainerHelper::getMapElement( maOleObjects, rShapeId ); @@ -143,21 +207,72 @@ const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const return ContainerHelper::getMapElement( maControls, rShapeId ); } +Reference< XShape > Drawing::createAndInsertXShape( const OUString& rService, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + OSL_ENSURE( rService.getLength() > 0, "Drawing::createAndInsertXShape - missing UNO shape service name" ); + OSL_ENSURE( rxShapes.is(), "Drawing::createAndInsertXShape - missing XShapes container" ); + Reference< XShape > xShape; + if( (rService.getLength() > 0) && rxShapes.is() ) try + { + Reference< XMultiServiceFactory > xFactory( mrFilter.getModelFactory(), UNO_SET_THROW ); + xShape.set( xFactory->createInstance( rService ), UNO_QUERY_THROW ); + // insert shape into passed shape collection (maybe drawpage or group shape) + rxShapes->add( xShape ); + xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) ); + xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xShape.is(), "Drawing::createAndInsertXShape - cannot instanciate shape object" ); + return xShape; +} + +Reference< XShape > Drawing::createAndInsertXControlShape( const ::oox::ole::EmbeddedControl& rControl, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect, sal_Int32& rnCtrlIndex ) const +{ + Reference< XShape > xShape; + try + { + // create control model and insert it into the form of the draw page + Reference< XControlModel > xCtrlModel( getControlForm().convertAndInsert( rControl, rnCtrlIndex ), UNO_SET_THROW ); + + // create the control shape + xShape = createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rxShapes, rShapeRect ); + + // set the control model at the shape + Reference< XControlShape >( xShape, UNO_QUERY_THROW )->setControl( xCtrlModel ); + } + catch( Exception& ) + { + } + return xShape; +} + bool Drawing::isShapeSupported( const ShapeBase& /*rShape*/ ) const { return true; } -bool Drawing::convertShapeClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const +OUString Drawing::getShapeBaseName( const ShapeBase& /*rShape*/ ) const +{ + return OUString(); +} + +bool Drawing::convertClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const { return false; } -void Drawing::convertControlClientData( const Reference< XControlModel >& /*rxCtrlModel*/, const ShapeClientData& /*rClientData*/ ) const +Reference< XShape > Drawing::createAndInsertClientXShape( const ShapeBase& /*rShape*/, + const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const { + return Reference< XShape >(); } -void Drawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const Rectangle& /*rShapeRect*/ ) +void Drawing::notifyXShapeInserted( const Reference< XShape >& /*rxShape*/, + const Rectangle& /*rShapeRect*/, const ShapeBase& /*rShape*/, bool /*bGroupChild*/ ) { } @@ -166,4 +281,4 @@ void Drawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const } // namespace vml } // namespave oox -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file |