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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmloff.hxx" 30 31 32 #include <tools/debug.hxx> 33 #ifndef __SGI_STL_SET 34 #include <set> 35 #endif 36 #include "xmloff/xmlnmspe.hxx" 37 #include <xmloff/xmltoken.hxx> 38 #include <xmloff/xmlprcon.hxx> 39 #include <com/sun/star/style/XStyle.hpp> 40 #include <com/sun/star/style/XAutoStyleFamily.hpp> 41 #include <com/sun/star/container/XNameContainer.hpp> 42 #include <com/sun/star/beans/XPropertySet.hpp> 43 #include <com/sun/star/beans/XPropertyState.hpp> 44 #include <com/sun/star/beans/XMultiPropertyStates.hpp> 45 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 46 #include <xmloff/xmlimp.hxx> 47 48 #ifndef _XMLOFF_PRSTYLEI_HXX 49 #include <xmloff/prstylei.hxx> 50 #endif 51 #include <xmloff/attrlist.hxx> 52 #include "xmloff/xmlerror.hxx" 53 54 using ::rtl::OUString; 55 using ::rtl::OUStringBuffer; 56 57 using namespace ::com::sun::star; 58 using namespace ::com::sun::star::uno; 59 using namespace ::com::sun::star::xml::sax; 60 using namespace ::com::sun::star::style; 61 using namespace ::com::sun::star::container; 62 using namespace ::com::sun::star::beans; 63 using namespace ::com::sun::star::lang; 64 using namespace ::xmloff::token; 65 66 67 void XMLPropStyleContext::SetAttribute( sal_uInt16 nPrefixKey, 68 const OUString& rLocalName, 69 const OUString& rValue ) 70 { 71 if( XML_NAMESPACE_STYLE == nPrefixKey && IsXMLToken( rLocalName, XML_FAMILY ) ) 72 { 73 DBG_ASSERT( GetFamily() == ((SvXMLStylesContext *)&mxStyles)->GetFamily( rValue ), "unexpected style family" ); 74 } 75 else 76 { 77 SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); 78 } 79 } 80 81 TYPEINIT1( XMLPropStyleContext, SvXMLStyleContext ); 82 83 XMLPropStyleContext::XMLPropStyleContext( SvXMLImport& rImport, 84 sal_uInt16 nPrfx, const OUString& rLName, 85 const Reference< XAttributeList > & xAttrList, 86 SvXMLStylesContext& rStyles, sal_uInt16 nFamily, 87 sal_Bool bDefault ) 88 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, nFamily, bDefault ) 89 , msIsPhysical( RTL_CONSTASCII_USTRINGPARAM( "IsPhysical" ) ) 90 , msFollowStyle( RTL_CONSTASCII_USTRINGPARAM( "FollowStyle" ) ) 91 , mxStyles( &rStyles ) 92 { 93 } 94 95 XMLPropStyleContext::~XMLPropStyleContext() 96 { 97 } 98 99 SvXMLImportContext *XMLPropStyleContext::CreateChildContext( 100 sal_uInt16 nPrefix, 101 const OUString& rLocalName, 102 const Reference< XAttributeList > & xAttrList ) 103 { 104 SvXMLImportContext *pContext = 0; 105 106 sal_uInt32 nFamily = 0; 107 if( XML_NAMESPACE_STYLE == nPrefix ) 108 { 109 if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) ) 110 nFamily = XML_TYPE_PROP_GRAPHIC; 111 else if( IsXMLToken( rLocalName, XML_DRAWING_PAGE_PROPERTIES ) ) 112 nFamily = XML_TYPE_PROP_DRAWING_PAGE; 113 else if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) ) 114 nFamily = XML_TYPE_PROP_TEXT; 115 else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) ) 116 nFamily = XML_TYPE_PROP_PARAGRAPH; 117 else if( IsXMLToken( rLocalName, XML_RUBY_PROPERTIES ) ) 118 nFamily = XML_TYPE_PROP_RUBY; 119 else if( IsXMLToken( rLocalName, XML_SECTION_PROPERTIES ) ) 120 nFamily = XML_TYPE_PROP_SECTION; 121 else if( IsXMLToken( rLocalName, XML_TABLE_PROPERTIES ) ) 122 nFamily = XML_TYPE_PROP_TABLE; 123 else if( IsXMLToken( rLocalName, XML_TABLE_COLUMN_PROPERTIES ) ) 124 nFamily = XML_TYPE_PROP_TABLE_COLUMN; 125 else if( IsXMLToken( rLocalName, XML_TABLE_ROW_PROPERTIES ) ) 126 nFamily = XML_TYPE_PROP_TABLE_ROW; 127 else if( IsXMLToken( rLocalName, XML_TABLE_CELL_PROPERTIES ) ) 128 nFamily = XML_TYPE_PROP_TABLE_CELL; 129 else if( IsXMLToken( rLocalName, XML_CHART_PROPERTIES ) ) 130 nFamily = XML_TYPE_PROP_CHART; 131 } 132 if( nFamily ) 133 { 134 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 135 ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( 136 GetFamily() ); 137 if( xImpPrMap.is() ) 138 pContext = new SvXMLPropertySetContext( GetImport(), nPrefix, 139 rLocalName, xAttrList, 140 nFamily, 141 maProperties, 142 xImpPrMap ); 143 } 144 145 if( !pContext ) 146 pContext = SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName, 147 xAttrList ); 148 149 return pContext; 150 } 151 152 void XMLPropStyleContext::FillPropertySet( 153 const Reference< XPropertySet > & rPropSet ) 154 { 155 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 156 ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( 157 GetFamily() ); 158 DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" ); 159 if( xImpPrMap.is() ) 160 xImpPrMap->FillPropertySet( maProperties, rPropSet ); 161 } 162 163 void XMLPropStyleContext::SetDefaults() 164 { 165 } 166 167 Reference < XStyle > XMLPropStyleContext::Create() 168 { 169 Reference < XStyle > xNewStyle; 170 171 OUString sServiceName( 172 ((SvXMLStylesContext *)&mxStyles)->GetServiceName( GetFamily() ) ); 173 if( sServiceName.getLength() ) 174 { 175 Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(), 176 UNO_QUERY ); 177 if( xFactory.is() ) 178 { 179 Reference < XInterface > xIfc = 180 xFactory->createInstance( sServiceName ); 181 if( xIfc.is() ) 182 xNewStyle = Reference < XStyle >( xIfc, UNO_QUERY ); 183 } 184 } 185 186 return xNewStyle; 187 } 188 189 typedef ::std::set < OUString, ::comphelper::UStringLess > PropertyNameSet; 190 191 void XMLPropStyleContext::CreateAndInsert( sal_Bool bOverwrite ) 192 { 193 if( ((SvXMLStylesContext *)&mxStyles)->IsAutomaticStyle() 194 && ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT || GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) ) 195 { 196 Reference < XAutoStyleFamily > xAutoFamily = 197 ((SvXMLStylesContext *)&mxStyles)->GetAutoStyles( GetFamily() ); 198 if( !xAutoFamily.is() ) 199 return; 200 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 201 ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( GetFamily() ); 202 DBG_ASSERT( xImpPrMap.is(), "There is no import prop mapper" ); 203 if( xImpPrMap.is() ) 204 { 205 Sequence< PropertyValue > aValues; 206 xImpPrMap->FillPropertySequence( maProperties, aValues ); 207 208 sal_Int32 nLen = aValues.getLength(); 209 if( nLen ) 210 { 211 if( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) 212 { 213 aValues.realloc( nLen + 2 ); 214 PropertyValue *pProps = aValues.getArray() + nLen; 215 pProps->Name = rtl::OUString::createFromAscii("ParaStyleName"); 216 OUString sParent( GetParentName() ); 217 if( sParent.getLength() ) 218 sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent ); 219 else 220 sParent = rtl::OUString::createFromAscii("Standard"); 221 pProps->Value <<= sParent; 222 ++pProps; 223 pProps->Name = rtl::OUString::createFromAscii("ParaConditionalStyleName"); 224 pProps->Value <<= sParent; 225 } 226 227 Reference < XAutoStyle > xAutoStyle = xAutoFamily->insertStyle( aValues ); 228 if( xAutoStyle.is() ) 229 { 230 Sequence< OUString > aPropNames(1); 231 aPropNames[0] = GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ? 232 rtl::OUString::createFromAscii("ParaAutoStyleName") : 233 rtl::OUString::createFromAscii("CharAutoStyleName"); 234 Sequence< Any > aAny = xAutoStyle->getPropertyValues( aPropNames ); 235 if( aAny.hasElements() ) 236 { 237 OUString aName; 238 aAny[0] >>= aName; 239 SetAutoName( aName ); 240 } 241 } 242 } 243 } 244 } 245 else 246 { 247 const OUString& rName = GetDisplayName(); 248 if( 0 == rName.getLength() || IsDefaultStyle() ) 249 return; 250 251 Reference < XNameContainer > xFamilies = 252 ((SvXMLStylesContext *)&mxStyles)->GetStylesContainer( GetFamily() ); 253 if( !xFamilies.is() ) 254 return; 255 256 sal_Bool bNew = sal_False; 257 if( xFamilies->hasByName( rName ) ) 258 { 259 Any aAny = xFamilies->getByName( rName ); 260 aAny >>= mxStyle; 261 } 262 else 263 { 264 mxStyle = Create(); 265 if( !mxStyle.is() ) 266 return; 267 268 Any aAny; 269 aAny <<= mxStyle; 270 xFamilies->insertByName( rName, aAny ); 271 bNew = sal_True; 272 } 273 274 Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY ); 275 Reference< XPropertySetInfo > xPropSetInfo = 276 xPropSet->getPropertySetInfo(); 277 if( !bNew && xPropSetInfo->hasPropertyByName( msIsPhysical ) ) 278 { 279 Any aAny = xPropSet->getPropertyValue( msIsPhysical ); 280 bNew = !*(sal_Bool *)aAny.getValue(); 281 } 282 SetNew( bNew ); 283 if( rName != GetName() ) 284 GetImport().AddStyleDisplayName( GetFamily(), GetName(), rName ); 285 286 if( bOverwrite || bNew ) 287 { 288 Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY ); 289 290 UniReference < XMLPropertySetMapper > xPrMap; 291 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 292 ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( 293 GetFamily() ); 294 DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" ); 295 if( xImpPrMap.is() ) 296 xPrMap = xImpPrMap->getPropertySetMapper(); 297 if( xPrMap.is() ) 298 { 299 Reference < XMultiPropertyStates > xMultiStates( xPropSet, 300 UNO_QUERY ); 301 if( xMultiStates.is() ) 302 { 303 xMultiStates->setAllPropertiesToDefault(); 304 } 305 else 306 { 307 PropertyNameSet aNameSet; 308 sal_Int32 nCount = xPrMap->GetEntryCount(); 309 sal_Int32 i; 310 for( i = 0; i < nCount; i++ ) 311 { 312 const OUString& rPrName = xPrMap->GetEntryAPIName( i ); 313 if( xPropSetInfo->hasPropertyByName( rPrName ) ) 314 aNameSet.insert( rPrName ); 315 } 316 317 nCount = aNameSet.size(); 318 Sequence < OUString > aNames( nCount ); 319 OUString *pNames = aNames.getArray(); 320 PropertyNameSet::iterator aIter = aNameSet.begin(); 321 while( aIter != aNameSet.end() ) 322 *pNames++ = *aIter++; 323 324 Sequence < PropertyState > aStates( 325 xPropState->getPropertyStates( aNames ) ); 326 const PropertyState *pStates = aStates.getConstArray(); 327 pNames = aNames.getArray(); 328 329 for( i = 0; i < nCount; i++ ) 330 { 331 if( PropertyState_DIRECT_VALUE == *pStates++ ) 332 xPropState->setPropertyToDefault( pNames[i] ); 333 } 334 } 335 } 336 337 if (mxStyle.is()) 338 mxStyle->setParentStyle(OUString()); 339 340 FillPropertySet( xPropSet ); 341 } 342 else 343 { 344 SetValid( sal_False ); 345 } 346 } 347 } 348 349 void XMLPropStyleContext::Finish( sal_Bool bOverwrite ) 350 { 351 if( mxStyle.is() && (IsNew() || bOverwrite) ) 352 { 353 // The families cintaner must exist 354 Reference < XNameContainer > xFamilies = 355 ((SvXMLStylesContext *)&mxStyles)->GetStylesContainer( GetFamily() ); 356 DBG_ASSERT( xFamilies.is(), "Families lost" ); 357 if( !xFamilies.is() ) 358 return; 359 360 // connect parent 361 OUString sParent( GetParentName() ); 362 if( sParent.getLength() ) 363 sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent ); 364 if( sParent.getLength() && !xFamilies->hasByName( sParent ) ) 365 sParent = OUString(); 366 367 if( sParent != mxStyle->getParentStyle() ) 368 { 369 // this may except if setting the parent style forms a 370 // circle in the style depencies; especially if the parent 371 // style is the same as the current style 372 try 373 { 374 mxStyle->setParentStyle( sParent ); 375 } 376 catch( uno::Exception e ) 377 { 378 // according to the API definition, I would expect a 379 // container::NoSuchElementException. But it throws an 380 // uno::RuntimeException instead. I catch 381 // uno::Exception in order to process both of them. 382 383 // We can't set the parent style. For a proper 384 // Error-Message, we should pass in the name of the 385 // style, as well as the desired parent style. 386 Sequence<OUString> aSequence(2); 387 388 // getName() throws no non-Runtime exception: 389 aSequence[0] = mxStyle->getName(); 390 aSequence[1] = sParent; 391 392 GetImport().SetError( 393 XMLERROR_FLAG_ERROR | XMLERROR_PARENT_STYLE_NOT_ALLOWED, 394 aSequence, e.Message, NULL ); 395 } 396 } 397 398 // connect follow 399 OUString sFollow( GetFollow() ); 400 if( sFollow.getLength() ) 401 sFollow = GetImport().GetStyleDisplayName( GetFamily(), sFollow ); 402 if( !sFollow.getLength() || !xFamilies->hasByName( sFollow ) ) 403 sFollow = mxStyle->getName(); 404 405 Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY ); 406 Reference< XPropertySetInfo > xPropSetInfo = 407 xPropSet->getPropertySetInfo(); 408 if( xPropSetInfo->hasPropertyByName( msFollowStyle ) ) 409 { 410 Any aAny = xPropSet->getPropertyValue( msFollowStyle ); 411 OUString sCurrFollow; 412 aAny >>= sCurrFollow; 413 if( sCurrFollow != sFollow ) 414 { 415 aAny <<= sFollow; 416 xPropSet->setPropertyValue( msFollowStyle, aAny ); 417 } 418 } 419 } 420 } 421 422 423