xref: /trunk/main/oox/source/vml/vmldrawing.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/vml/vmldrawing.hxx"
29 
30 #include <algorithm>
31 #include <com/sun/star/drawing/XControlShape.hpp>
32 #include <com/sun/star/drawing/XShapes.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include "oox/core/xmlfilterbase.hxx"
35 #include "oox/helper/containerhelper.hxx"
36 #include "oox/ole/axcontrol.hxx"
37 #include "oox/vml/vmlshape.hxx"
38 #include "oox/vml/vmlshapecontainer.hxx"
39 
40 namespace oox {
41 namespace vml {
42 
43 // ============================================================================
44 
45 using namespace ::com::sun::star::awt;
46 using namespace ::com::sun::star::drawing;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::uno;
49 
50 using ::oox::core::XmlFilterBase;
51 using ::rtl::OUString;
52 
53 // ============================================================================
54 
55 namespace {
56 
57 /** Returns the textual representation of a numeric VML shape identifier. */
58 OUString lclGetShapeId( sal_Int32 nShapeId )
59 {
60     // identifier consists of a literal NUL character, a lowercase 's', and the id
61     return CREATE_OUSTRING( "\0s" ) + OUString::valueOf( nShapeId );
62 }
63 
64 /** Returns the numeric VML shape identifier from its textual representation. */
65 sal_Int32 lclGetShapeId( const OUString& rShapeId )
66 {
67     // identifier consists of a literal NUL character, a lowercase 's', and the id
68     return ((rShapeId.getLength() >= 3) && (rShapeId[ 0 ] == '\0') && (rShapeId[ 1 ] == 's')) ? rShapeId.copy( 2 ).toInt32() : -1;
69 }
70 
71 } // namespace
72 
73 // ============================================================================
74 
75 OleObjectInfo::OleObjectInfo( bool bDmlShape ) :
76     mbAutoLoad( false ),
77     mbDmlShape( bDmlShape )
78 {
79 }
80 
81 void OleObjectInfo::setShapeId( sal_Int32 nShapeId )
82 {
83     maShapeId = lclGetShapeId( nShapeId );
84 }
85 
86 // ============================================================================
87 
88 ControlInfo::ControlInfo()
89 {
90 }
91 
92 void ControlInfo::setShapeId( sal_Int32 nShapeId )
93 {
94     maShapeId = lclGetShapeId( nShapeId );
95 }
96 
97 // ============================================================================
98 
99 Drawing::Drawing( XmlFilterBase& rFilter, const Reference< XDrawPage >& rxDrawPage, DrawingType eType ) :
100     mrFilter( rFilter ),
101     mxDrawPage( rxDrawPage ),
102     mxShapes( new ShapeContainer( *this ) ),
103     meType( eType )
104 {
105     OSL_ENSURE( mxDrawPage.is(), "Drawing::Drawing - missing UNO draw page" );
106 }
107 
108 Drawing::~Drawing()
109 {
110 }
111 
112 ::oox::ole::EmbeddedForm& Drawing::getControlForm() const
113 {
114     if( !mxCtrlForm.get() )
115         mxCtrlForm.reset( new ::oox::ole::EmbeddedForm(
116             mrFilter.getModel(), mxDrawPage, mrFilter.getGraphicHelper() ) );
117     return *mxCtrlForm;
118 }
119 
120 void Drawing::registerBlockId( sal_Int32 nBlockId )
121 {
122     OSL_ENSURE( nBlockId > 0, "Drawing::registerBlockId - invalid block index" );
123     if( nBlockId > 0 )
124     {
125         // lower_bound() returns iterator pointing to element equal to nBlockId, if existing
126         BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId );
127         if( (aIt == maBlockIds.end()) || (nBlockId != *aIt) )
128             maBlockIds.insert( aIt, nBlockId );
129     }
130 }
131 
132 void Drawing::registerOleObject( const OleObjectInfo& rOleObject )
133 {
134     OSL_ENSURE( rOleObject.maShapeId.getLength() > 0, "Drawing::registerOleObject - missing OLE object shape id" );
135     OSL_ENSURE( maOleObjects.count( rOleObject.maShapeId ) == 0, "Drawing::registerOleObject - OLE object already registered" );
136     maOleObjects.insert( OleObjectInfoMap::value_type( rOleObject.maShapeId, rOleObject ) );
137 }
138 
139 void Drawing::registerControl( const ControlInfo& rControl )
140 {
141     OSL_ENSURE( rControl.maShapeId.getLength() > 0, "Drawing::registerControl - missing form control shape id" );
142     OSL_ENSURE( rControl.maName.getLength() > 0, "Drawing::registerControl - missing form control name" );
143     OSL_ENSURE( maControls.count( rControl.maShapeId ) == 0, "Drawing::registerControl - form control already registered" );
144     maControls.insert( ControlInfoMap::value_type( rControl.maShapeId, rControl ) );
145 }
146 
147 void Drawing::finalizeFragmentImport()
148 {
149     mxShapes->finalizeFragmentImport();
150 }
151 
152 void Drawing::convertAndInsert() const
153 {
154     Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY );
155     mxShapes->convertAndInsert( xShapes );
156 }
157 
158 sal_Int32 Drawing::getLocalShapeIndex( const OUString& rShapeId ) const
159 {
160     sal_Int32 nShapeId = lclGetShapeId( rShapeId );
161     if( nShapeId <= 0 ) return -1;
162 
163     /*  Shapes in a drawing are counted per registered shape identifier blocks
164         as stored in the o:idmap element. The contents of this element have
165         been stored in our member maBlockIds. Each block represents 1024 shape
166         identifiers, starting with identifier 1 for the block #0. This means,
167         block #0 represents the identifiers 1-1024, block #1 represents the
168         identifiers 1025-2048, and so on. The local shape index has to be
169         calculated according to all blocks registered for this drawing.
170 
171         Example:
172             Registered for this drawing are blocks #1 and #3 (shape identifiers
173             1025-2048 and 3073-4096).
174             Shape identifier 1025 -> local shape index 1.
175             Shape identifier 1026 -> local shape index 2.
176             ...
177             Shape identifier 2048 -> local shape index 1024.
178             Shape identifier 3073 -> local shape index 1025.
179             ...
180             Shape identifier 4096 -> local shape index 2048.
181      */
182 
183     // get block id from shape id and find its index in the list of used blocks
184     sal_Int32 nBlockId = (nShapeId - 1) / 1024;
185     BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId );
186     sal_Int32 nIndex = static_cast< sal_Int32 >( aIt - maBlockIds.begin() );
187 
188     // block id not found in set -> register it now (value of nIndex remains valid)
189     if( (aIt == maBlockIds.end()) || (*aIt != nBlockId) )
190         maBlockIds.insert( aIt, nBlockId );
191 
192     // get one-based offset of shape id in its block
193     sal_Int32 nBlockOffset = (nShapeId - 1) % 1024 + 1;
194 
195     // calculate the local shape index
196     return 1024 * nIndex + nBlockOffset;
197 }
198 
199 const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const
200 {
201     return ContainerHelper::getMapElement( maOleObjects, rShapeId );
202 }
203 
204 const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const
205 {
206     return ContainerHelper::getMapElement( maControls, rShapeId );
207 }
208 
209 Reference< XShape > Drawing::createAndInsertXShape( const OUString& rService,
210         const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
211 {
212     OSL_ENSURE( rService.getLength() > 0, "Drawing::createAndInsertXShape - missing UNO shape service name" );
213     OSL_ENSURE( rxShapes.is(), "Drawing::createAndInsertXShape - missing XShapes container" );
214     Reference< XShape > xShape;
215     if( (rService.getLength() > 0) && rxShapes.is() ) try
216     {
217         Reference< XMultiServiceFactory > xModelFactory( mrFilter.getModelFactory(), UNO_SET_THROW );
218         xShape.set( xModelFactory->createInstance( rService ), UNO_QUERY_THROW );
219         // insert shape into passed shape collection (maybe drawpage or group shape)
220         rxShapes->add( xShape );
221         xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
222         xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
223     }
224     catch( Exception& )
225     {
226     }
227     OSL_ENSURE( xShape.is(), "Drawing::createAndInsertXShape - cannot instanciate shape object" );
228     return xShape;
229 }
230 
231 Reference< XShape > Drawing::createAndInsertXControlShape( const ::oox::ole::EmbeddedControl& rControl,
232         const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect, sal_Int32& rnCtrlIndex ) const
233 {
234     Reference< XShape > xShape;
235     try
236     {
237         // create control model and insert it into the form of the draw page
238         Reference< XControlModel > xCtrlModel( getControlForm().convertAndInsert( rControl, rnCtrlIndex ), UNO_SET_THROW );
239 
240         // create the control shape
241         xShape = createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rxShapes, rShapeRect );
242 
243         // set the control model at the shape
244         Reference< XControlShape >( xShape, UNO_QUERY_THROW )->setControl( xCtrlModel );
245     }
246     catch( Exception& )
247     {
248     }
249     return xShape;
250 }
251 
252 bool Drawing::isShapeSupported( const ShapeBase& /*rShape*/ ) const
253 {
254     return true;
255 }
256 
257 OUString Drawing::getShapeBaseName( const ShapeBase& /*rShape*/ ) const
258 {
259     return OUString();
260 }
261 
262 bool Drawing::convertClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const
263 {
264     return false;
265 }
266 
267 Reference< XShape > Drawing::createAndInsertClientXShape( const ShapeBase& /*rShape*/,
268         const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const
269 {
270     return Reference< XShape >();
271 }
272 
273 void Drawing::notifyXShapeInserted( const Reference< XShape >& /*rxShape*/,
274         const Rectangle& /*rShapeRect*/, const ShapeBase& /*rShape*/, bool /*bGroupChild*/ )
275 {
276 }
277 
278 // ============================================================================
279 
280 } // namespace vml
281 } // namespave oox
282