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