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_svx.hxx" 30 31 #include <set> 32 #include <comphelper/stl_types.hxx> 33 #include <com/sun/star/lang/XServiceInfo.hpp> 34 #include <com/sun/star/container/XNameContainer.hpp> 35 #include <com/sun/star/drawing/PointSequence.hpp> 36 #include <svl/style.hxx> 37 38 #include <cppuhelper/implbase2.hxx> 39 #include <svl/itempool.hxx> 40 #include <svl/itemset.hxx> 41 #include <svl/lstner.hxx> 42 #include <svx/xlnedit.hxx> 43 #include <svx/xlnstit.hxx> 44 #include <svx/svdmodel.hxx> 45 #include <svx/xdef.hxx> 46 #include <svx/xflhtit.hxx> 47 48 #include <vector> 49 #include <vos/mutex.hxx> 50 #include <vcl/svapp.hxx> 51 52 53 #include "svx/unofill.hxx" 54 55 #include "svx/unoapi.hxx" 56 57 using namespace ::com::sun::star; 58 using namespace ::rtl; 59 using namespace ::cppu; 60 using namespace ::vos; 61 62 typedef std::vector< SfxItemSet* > ItemPoolVector; 63 64 class SvxUnoMarkerTable : public WeakImplHelper2< container::XNameContainer, lang::XServiceInfo >, 65 public SfxListener 66 { 67 private: 68 SdrModel* mpModel; 69 SfxItemPool* mpModelPool; 70 71 ItemPoolVector maItemSetVector; 72 73 public: 74 SvxUnoMarkerTable( SdrModel* pModel ) throw(); 75 virtual ~SvxUnoMarkerTable() throw(); 76 77 void dispose(); 78 79 // SfxListener 80 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) throw (); 81 82 void SAL_CALL ImplInsertByName( const OUString& aName, const uno::Any& aElement ); 83 84 // XServiceInfo 85 virtual OUString SAL_CALL getImplementationName( ) throw( uno::RuntimeException ); 86 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw( uno::RuntimeException); 87 virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw( uno::RuntimeException); 88 89 // XNameContainer 90 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException); 91 virtual void SAL_CALL removeByName( const OUString& Name ) throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException); 92 93 // XNameReplace 94 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException); 95 96 // XNameAccess 97 virtual uno::Any SAL_CALL getByName( const OUString& aName ) throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException); 98 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) throw( uno::RuntimeException); 99 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw( uno::RuntimeException); 100 101 // XElementAccess 102 virtual uno::Type SAL_CALL getElementType( ) throw( uno::RuntimeException); 103 virtual sal_Bool SAL_CALL hasElements( ) throw( uno::RuntimeException); 104 }; 105 106 SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel* pModel ) throw() 107 : mpModel( pModel ), 108 mpModelPool( pModel ? &pModel->GetItemPool() : (SfxItemPool*)NULL ) 109 { 110 if( pModel ) 111 StartListening( *pModel ); 112 } 113 114 SvxUnoMarkerTable::~SvxUnoMarkerTable() throw() 115 { 116 if( mpModel ) 117 EndListening( *mpModel ); 118 dispose(); 119 } 120 121 void SvxUnoMarkerTable::dispose() 122 { 123 ItemPoolVector::iterator aIter = maItemSetVector.begin(); 124 const ItemPoolVector::iterator aEnd = maItemSetVector.end(); 125 126 while( aIter != aEnd ) 127 { 128 delete (*aIter++); 129 } 130 131 maItemSetVector.clear(); 132 } 133 134 // SfxListener 135 void SvxUnoMarkerTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) throw() 136 { 137 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint ); 138 139 if( pSdrHint && HINT_MODELCLEARED == pSdrHint->GetKind() ) 140 dispose(); 141 } 142 143 sal_Bool SAL_CALL SvxUnoMarkerTable::supportsService( const OUString& ServiceName ) throw(uno::RuntimeException) 144 { 145 uno::Sequence< OUString > aSNL( getSupportedServiceNames() ); 146 const OUString * pArray = aSNL.getConstArray(); 147 148 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 149 if( pArray[i] == ServiceName ) 150 return sal_True; 151 152 return sal_False; 153 } 154 155 OUString SAL_CALL SvxUnoMarkerTable::getImplementationName() throw( uno::RuntimeException ) 156 { 157 return OUString( RTL_CONSTASCII_USTRINGPARAM("SvxUnoMarkerTable") ); 158 } 159 160 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getSupportedServiceNames( ) 161 throw( uno::RuntimeException ) 162 { 163 uno::Sequence< OUString > aSNS( 1 ); 164 aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.MarkerTable" )); 165 return aSNS; 166 } 167 168 void SAL_CALL SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement ) 169 { 170 SfxItemSet* mpInSet = new SfxItemSet( *mpModelPool, XATTR_LINESTART, XATTR_LINEEND ); 171 maItemSetVector.push_back( mpInSet ); 172 173 XLineEndItem aEndMarker; 174 aEndMarker.SetName( String( aName ) ); 175 aEndMarker.PutValue( aElement ); 176 177 mpInSet->Put( aEndMarker, XATTR_LINEEND ); 178 179 XLineStartItem aStartMarker; 180 aStartMarker.SetName( String( aName ) ); 181 aStartMarker.PutValue( aElement ); 182 183 mpInSet->Put( aStartMarker, XATTR_LINESTART ); 184 } 185 186 // XNameContainer 187 void SAL_CALL SvxUnoMarkerTable::insertByName( const OUString& aApiName, const uno::Any& aElement ) 188 throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException ) 189 { 190 OGuard aGuard( Application::GetSolarMutex() ); 191 192 if( hasByName( aApiName ) ) 193 throw container::ElementExistException(); 194 195 String aName; 196 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 197 198 ImplInsertByName( aName, aElement ); 199 } 200 201 void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName ) 202 throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 203 { 204 OGuard aGuard( Application::GetSolarMutex() ); 205 206 // a little quickfix for 2.0 to let applications clear api 207 // created items that are not used 208 if( aApiName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("~clear~") ) ) 209 { 210 dispose(); 211 return; 212 } 213 214 String Name; 215 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, Name ); 216 217 ItemPoolVector::iterator aIter = maItemSetVector.begin(); 218 const ItemPoolVector::iterator aEnd = maItemSetVector.end(); 219 220 NameOrIndex *pItem; 221 const String aSearchName( Name ); 222 223 while( aIter != aEnd ) 224 { 225 pItem = (NameOrIndex *)&((*aIter)->Get( XATTR_LINEEND ) ); 226 if( pItem->GetName() == aSearchName ) 227 { 228 delete (*aIter); 229 maItemSetVector.erase( aIter ); 230 return; 231 } 232 aIter++; 233 } 234 235 if( !hasByName( Name ) ) 236 throw container::NoSuchElementException(); 237 } 238 239 // XNameReplace 240 void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement ) 241 throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException ) 242 { 243 OGuard aGuard( Application::GetSolarMutex() ); 244 245 String aName; 246 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 247 248 ItemPoolVector::iterator aIter = maItemSetVector.begin(); 249 const ItemPoolVector::iterator aEnd = maItemSetVector.end(); 250 251 NameOrIndex *pItem; 252 const String aSearchName( aName ); 253 254 while( aIter != aEnd ) 255 { 256 pItem = (NameOrIndex *)&((*aIter)->Get( XATTR_LINEEND ) ); 257 if( pItem->GetName() == aSearchName ) 258 { 259 XLineEndItem aEndMarker; 260 aEndMarker.SetName( aSearchName ); 261 if( !aEndMarker.PutValue( aElement ) ) 262 throw lang::IllegalArgumentException(); 263 264 (*aIter)->Put( aEndMarker, XATTR_LINEEND ); 265 266 XLineStartItem aStartMarker; 267 aStartMarker.SetName( aSearchName ); 268 aStartMarker.PutValue( aElement ); 269 270 (*aIter)->Put( aStartMarker, XATTR_LINESTART ); 271 return; 272 } 273 aIter++; 274 } 275 276 // if it is not in our own sets, modify the pool! 277 sal_Bool bFound = sal_False; 278 279 sal_uInt32 nSurrogate; 280 const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 281 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 282 { 283 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 284 if( pItem && pItem->GetName() == aSearchName ) 285 { 286 pItem->PutValue( aElement ); 287 bFound = sal_True; 288 break; 289 } 290 } 291 292 const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 293 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 294 { 295 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 296 if( pItem && pItem->GetName() == aSearchName ) 297 { 298 pItem->PutValue( aElement ); 299 bFound = sal_True; 300 break; 301 } 302 } 303 304 if( bFound ) 305 ImplInsertByName( aName, aElement ); 306 else 307 throw container::NoSuchElementException(); 308 } 309 310 static sal_Bool getByNameFromPool( const String& rSearchName, SfxItemPool* pPool, sal_uInt16 nWhich, uno::Any& rAny ) 311 { 312 NameOrIndex *pItem; 313 const sal_uInt32 nSurrogateCount = pPool ? pPool->GetItemCount2( nWhich ) : 0; 314 for( sal_uInt32 nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ ) 315 { 316 pItem = (NameOrIndex*)pPool->GetItem2( nWhich, nSurrogate ); 317 318 if( pItem && pItem->GetName() == rSearchName ) 319 { 320 pItem->QueryValue( rAny, 0 ); 321 return sal_True; 322 } 323 } 324 325 return sal_False; 326 } 327 328 // XNameAccess 329 uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName ) 330 throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 331 { 332 OGuard aGuard( Application::GetSolarMutex() ); 333 334 String aName; 335 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 336 337 uno::Any aAny; 338 339 if( mpModelPool && aName.Len() != 0 ) 340 { 341 do 342 { 343 const String aSearchName( aName ); 344 if( getByNameFromPool( aSearchName, mpModelPool, XATTR_LINESTART, aAny ) ) 345 break; 346 347 if( getByNameFromPool( aSearchName, mpModelPool, XATTR_LINEEND, aAny ) ) 348 break; 349 350 throw container::NoSuchElementException(); 351 } 352 while(0); 353 } 354 355 return aAny; 356 } 357 358 static void createNamesForPool( SfxItemPool* pPool, sal_uInt16 nWhich, std::set< OUString, comphelper::UStringLess >& rNameSet ) 359 { 360 const sal_uInt32 nSuroCount = pPool->GetItemCount2( nWhich ); 361 sal_uInt32 nSurrogate; 362 363 NameOrIndex* pItem; 364 OUString aName; 365 366 for( nSurrogate = 0; nSurrogate < nSuroCount; nSurrogate++ ) 367 { 368 pItem = (NameOrIndex*)pPool->GetItem2( nWhich, nSurrogate ); 369 370 if( pItem == NULL || pItem->GetName().Len() == 0 ) 371 continue; 372 373 SvxUnogetApiNameForItem( XATTR_LINEEND, pItem->GetName(), aName ); 374 rNameSet.insert( aName ); 375 } 376 } 377 378 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames() 379 throw( uno::RuntimeException ) 380 { 381 OGuard aGuard( Application::GetSolarMutex() ); 382 383 std::set< OUString, comphelper::UStringLess > aNameSet; 384 385 // search model pool for line starts 386 createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet ); 387 388 // search model pool for line ends 389 createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet ); 390 391 uno::Sequence< OUString > aSeq( aNameSet.size() ); 392 OUString* pNames = aSeq.getArray(); 393 394 std::set< OUString, comphelper::UStringLess >::iterator aIter( aNameSet.begin() ); 395 const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aNameSet.end() ); 396 397 while( aIter != aEnd ) 398 { 399 *pNames++ = *aIter++; 400 } 401 402 return aSeq; 403 } 404 405 sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName ) 406 throw( uno::RuntimeException ) 407 { 408 OGuard aGuard( Application::GetSolarMutex() ); 409 410 if( aName.getLength() == 0 ) 411 return sal_False; 412 413 String aSearchName; 414 415 NameOrIndex *pItem; 416 417 SvxUnogetInternalNameForItem( XATTR_LINESTART, aName, aSearchName ); 418 sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 419 sal_uInt32 nSurrogate; 420 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 421 { 422 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 423 if( pItem && pItem->GetName() == aSearchName ) 424 return sal_True; 425 } 426 427 SvxUnogetInternalNameForItem( XATTR_LINEEND, aName, aSearchName ); 428 sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 429 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 430 { 431 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 432 if( pItem && pItem->GetName() == aSearchName ) 433 return sal_True; 434 } 435 436 return sal_False; 437 } 438 439 // XElementAccess 440 uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( ) 441 throw( uno::RuntimeException ) 442 { 443 return ::getCppuType((const drawing::PointSequence*)0); 444 } 445 446 sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( ) 447 throw( uno::RuntimeException ) 448 { 449 OGuard aGuard( Application::GetSolarMutex() ); 450 451 NameOrIndex *pItem; 452 453 const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 454 sal_uInt32 nSurrogate; 455 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 456 { 457 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 458 if( pItem && pItem->GetName().Len() != 0 ) 459 return sal_True; 460 } 461 462 const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 463 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 464 { 465 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 466 if( pItem && pItem->GetName().Len() != 0 ) 467 return sal_True; 468 } 469 470 return sal_False; 471 } 472 473 /** 474 * Create a hatchtable 475 */ 476 uno::Reference< uno::XInterface > SAL_CALL SvxUnoMarkerTable_createInstance( SdrModel* pModel ) 477 { 478 return *new SvxUnoMarkerTable(pModel); 479 } 480 481 482 483