update dev300-m58
[ooovba.git] / oox / source / vml / vmlshapecontext.cxx
blobdcf842a67a8f46a6e5ce76a74871c66e6b58146d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vmldrawingfragmenthandler.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/vml/vmlshapecontext.hxx"
32 #include "oox/vml/vmlshape.hxx"
33 #include "oox/vml/vmlshapecontainer.hxx"
35 using ::rtl::OUString;
36 using ::com::sun::star::awt::Point;
37 using ::oox::core::ContextHandler2;
38 using ::oox::core::ContextHandler2Helper;
39 using ::oox::core::ContextHandlerRef;
41 namespace oox {
42 namespace vml {
44 // ============================================================================
46 namespace {
48 bool lclSeparateValue( OUString& orName, OUString& orValue, const OUString& rAttrib, sal_Unicode cSep = ':' )
50 sal_Int32 nSepPos = rAttrib.indexOf( cSep );
51 if( nSepPos <= 0 ) return false;
52 orName = rAttrib.copy( 0, nSepPos ).trim();
53 orValue = rAttrib.copy( nSepPos + 1 ).trim();
54 return (orName.getLength() > 0) && (orValue.getLength() > 0);
57 /** Returns the boolean value from the passed string (supported: f, t, False, True).
58 @param bDefaultForEmpty Default value for the empty string.
60 bool lclDecodeBool( const OUString& rValue, bool bDefaultForEmpty )
62 if( rValue.getLength() == 0 ) return bDefaultForEmpty;
63 // anything else than 't' or 'True' is considered to be false, as specified
64 return ((rValue.getLength() == 1) && (rValue[ 0 ] == 't')) || (rValue == CREATE_OUSTRING( "True" ));
67 } // namespace
69 // ============================================================================
71 ShapeClientDataContext::ShapeClientDataContext( ContextHandler2Helper& rParent,
72 const AttributeList& rAttribs, ShapeClientData& rClientData ) :
73 ContextHandler2( rParent ),
74 mrClientData( rClientData )
76 mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID );
79 ContextHandlerRef ShapeClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
81 return isRootElement() ? this : 0;
84 void ShapeClientDataContext::onEndElement( const OUString& rChars )
86 switch( getCurrentElement() )
88 case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = rChars; break;
89 case VMLX_TOKEN( FmlaLink ): mrClientData.maLinkedCell = rChars; break;
90 case VMLX_TOKEN( FmlaPict ): mrClientData.maPictureLink = rChars; break;
91 case VMLX_TOKEN( FmlaRange ): mrClientData.maSourceRange = rChars; break;
92 case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeBool( rChars, true ); break;
96 // ============================================================================
98 ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
99 ContextHandler2( rParent )
103 /*static*/ ContextHandlerRef ShapeContextBase::createContext( ContextHandler2Helper& rParent,
104 sal_Int32 nElement, const AttributeList& rAttribs, ShapeContainer& rShapes )
106 switch( nElement )
108 case VML_TOKEN( shapetype ):
109 return new ShapeTypeContext( rParent, rAttribs, rShapes.createShapeType() );
110 case VML_TOKEN( group ):
111 return new GroupShapeContext( rParent, rAttribs, rShapes.createShape< GroupShape >() );
112 case VML_TOKEN( shape ):
113 return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() );
114 case VML_TOKEN( rect ):
115 case VML_TOKEN( roundrect ):
116 return new ShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() );
117 case VML_TOKEN( oval ):
118 return new ShapeContext( rParent, rAttribs, rShapes.createShape< EllipseShape >() );
119 case VML_TOKEN( polyline ):
120 return new ShapeContext( rParent, rAttribs, rShapes.createShape< PolyLineShape >() );
122 // TODO:
123 case VML_TOKEN( arc ):
124 case VML_TOKEN( curve ):
125 case VML_TOKEN( line ):
126 case VML_TOKEN( diagram ):
127 case VML_TOKEN( image ):
128 return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() );
130 return false;
133 // ============================================================================
135 ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeType& rShapeType ) :
136 ShapeContextBase( rParent ),
137 mrTypeModel( rShapeType.getTypeModel() )
139 // shape identifier and shape name
140 bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) );
141 mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() );
142 OSL_ENSURE( mrTypeModel.maShapeId.getLength() > 0, "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
143 // if the o:spid attribute exists, the id attribute contains the user-defined shape name
144 if( bHasOspid )
145 mrTypeModel.maName = rAttribs.getXString( XML_id, OUString() );
146 // builtin shape type identifier
147 mrTypeModel.monShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
148 // coordinate system position/size
149 setCoordOrigin( rAttribs.getString( XML_coordorigin, OUString() ) );
150 setCoordSize( rAttribs.getString( XML_coordsize, OUString() ) );
151 // CSS style
152 setStyle( rAttribs.getString( XML_style, OUString() ) );
153 // border line
154 mrTypeModel.mobStroked = rAttribs.getBool( XML_stroked );
155 mrTypeModel.moStrokeColor = rAttribs.getString( XML_strokecolor );
156 // shape fill
157 mrTypeModel.mobFilled = rAttribs.getBool( XML_filled );
158 mrTypeModel.moFillColor = rAttribs.getString( XML_fillcolor );
161 ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
163 if( isRootElement() ) switch( nElement )
165 case VML_TOKEN( imagedata ):
166 OptValue< OUString > oGraphicRelId = rAttribs.getString( O_TOKEN( relid ) );
167 if( oGraphicRelId.has() )
168 mrTypeModel.moGraphicPath = getFragmentPathFromRelId( oGraphicRelId.get() );
169 mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) );
170 break;
172 return 0;
175 void ShapeTypeContext::setCoordOrigin( const OUString& rCoordOrigin )
177 OUString aCoordL, aCoordT;
178 if( lclSeparateValue( aCoordL, aCoordT, rCoordOrigin, ',' ) )
180 mrTypeModel.monCoordLeft = aCoordL.toInt32();
181 mrTypeModel.monCoordTop = aCoordT.toInt32();
185 void ShapeTypeContext::setCoordSize( const OUString& rCoordSize )
187 OUString aCoordW, aCoordH;
188 if( lclSeparateValue( aCoordW, aCoordH, rCoordSize, ',' ) )
190 mrTypeModel.monCoordWidth = aCoordW.toInt32();
191 mrTypeModel.monCoordHeight = aCoordH.toInt32();
195 void ShapeTypeContext::setStyle( const OUString& rStyle )
197 sal_Int32 nIndex = 0;
198 while( nIndex >= 0 )
200 OUString aName, aValue;
201 if( lclSeparateValue( aName, aValue, rStyle.getToken( 0, ';', nIndex ) ) )
203 if( aName.equalsAscii( "position" ) ) mrTypeModel.maPosition = aValue;
204 else if( aName.equalsAscii( "left" ) ) mrTypeModel.maLeft = aValue;
205 else if( aName.equalsAscii( "top" ) ) mrTypeModel.maTop = aValue;
206 else if( aName.equalsAscii( "width" ) ) mrTypeModel.maWidth = aValue;
207 else if( aName.equalsAscii( "height" ) ) mrTypeModel.maHeight = aValue;
208 else if( aName.equalsAscii( "margin-left" ) ) mrTypeModel.maMarginLeft = aValue;
209 else if( aName.equalsAscii( "margin-top" ) ) mrTypeModel.maMarginTop = aValue;
214 // ============================================================================
216 ShapeContext::ShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeBase& rShape ) :
217 ShapeTypeContext( rParent, rAttribs, rShape ),
218 mrShapeModel( rShape.getShapeModel() )
220 // collect shape specific attributes
221 mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() );
222 // polyline path
223 setPoints( rAttribs.getString( XML_points, OUString() ) );
226 ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
228 // Excel specific shape client data
229 if( isRootElement() && (nElement == VMLX_TOKEN( ClientData )) )
230 return new ShapeClientDataContext( *this, rAttribs, mrShapeModel.createClientData() );
231 // handle remaining stuff in base class
232 return ShapeTypeContext::onCreateContext( nElement, rAttribs );
235 void ShapeContext::setPoints( const OUString& rPoints )
237 mrShapeModel.maPoints.clear();
238 sal_Int32 nIndex = 0;
239 while( nIndex >= 0 )
241 sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32();
242 sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32();
243 mrShapeModel.maPoints.push_back( Point( nX, nY ) );
247 // ============================================================================
249 GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, GroupShape& rShape ) :
250 ShapeContext( rParent, rAttribs, rShape ),
251 mrShapes( rShape.getChildren() )
255 ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
257 // try to create a context of an embedded shape
258 ContextHandlerRef xContext = ShapeContextBase::createContext( *this, nElement, rAttribs, mrShapes );
259 // handle remaining stuff of this shape in base class
260 return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs );
263 // ============================================================================
265 } // namespace vml
266 } // namespace oox