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( ); 82 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ); 83 virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ); 84 85 // XNameContainer 86 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ); 87 virtual void SAL_CALL removeByName( const OUString& Name ); 88 89 // XNameReplace 90 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ); 91 92 // XNameAccess 93 virtual uno::Any SAL_CALL getByName( const OUString& aName ); 94 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ); 95 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ); 96 97 // XElementAccess 98 virtual uno::Type SAL_CALL getElementType( ); 99 virtual sal_Bool SAL_CALL hasElements( ); 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 ) 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() 152 { 153 return OUString( RTL_CONSTASCII_USTRINGPARAM("SvxUnoMarkerTable") ); 154 } 155 156 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getSupportedServiceNames( ) 157 { 158 uno::Sequence< OUString > aSNS( 1 ); 159 aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.MarkerTable" )); 160 return aSNS; 161 } 162 163 void SAL_CALL SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement ) 164 { 165 SfxItemSet* mpInSet = new SfxItemSet( *mpModelPool, XATTR_LINESTART, XATTR_LINEEND ); 166 maItemSetVector.push_back( mpInSet ); 167 168 XLineEndItem aEndMarker; 169 aEndMarker.SetName( String( aName ) ); 170 aEndMarker.PutValue( aElement ); 171 172 mpInSet->Put( aEndMarker, XATTR_LINEEND ); 173 174 XLineStartItem aStartMarker; 175 aStartMarker.SetName( String( aName ) ); 176 aStartMarker.PutValue( aElement ); 177 178 mpInSet->Put( aStartMarker, XATTR_LINESTART ); 179 } 180 181 // XNameContainer 182 void SAL_CALL SvxUnoMarkerTable::insertByName( const OUString& aApiName, const uno::Any& aElement ) 183 { 184 OGuard aGuard( Application::GetSolarMutex() ); 185 186 if( hasByName( aApiName ) ) 187 throw container::ElementExistException(); 188 189 String aName; 190 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 191 192 ImplInsertByName( aName, aElement ); 193 } 194 195 void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName ) 196 { 197 OGuard aGuard( Application::GetSolarMutex() ); 198 199 // a little quickfix for 2.0 to let applications clear api 200 // created items that are not used 201 if( aApiName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("~clear~") ) ) 202 { 203 dispose(); 204 return; 205 } 206 207 String Name; 208 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, Name ); 209 210 ItemPoolVector::iterator aIter = maItemSetVector.begin(); 211 const ItemPoolVector::iterator aEnd = maItemSetVector.end(); 212 213 NameOrIndex *pItem; 214 const String aSearchName( Name ); 215 216 while( aIter != aEnd ) 217 { 218 pItem = (NameOrIndex *)&((*aIter)->Get( XATTR_LINEEND ) ); 219 if( pItem->GetName() == aSearchName ) 220 { 221 delete (*aIter); 222 maItemSetVector.erase( aIter ); 223 return; 224 } 225 aIter++; 226 } 227 228 if( !hasByName( Name ) ) 229 throw container::NoSuchElementException(); 230 } 231 232 // XNameReplace 233 void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement ) 234 { 235 OGuard aGuard( Application::GetSolarMutex() ); 236 237 String aName; 238 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 239 240 ItemPoolVector::iterator aIter = maItemSetVector.begin(); 241 const ItemPoolVector::iterator aEnd = maItemSetVector.end(); 242 243 NameOrIndex *pItem; 244 const String aSearchName( aName ); 245 246 while( aIter != aEnd ) 247 { 248 pItem = (NameOrIndex *)&((*aIter)->Get( XATTR_LINEEND ) ); 249 if( pItem->GetName() == aSearchName ) 250 { 251 XLineEndItem aEndMarker; 252 aEndMarker.SetName( aSearchName ); 253 if( !aEndMarker.PutValue( aElement ) ) 254 throw lang::IllegalArgumentException(); 255 256 (*aIter)->Put( aEndMarker, XATTR_LINEEND ); 257 258 XLineStartItem aStartMarker; 259 aStartMarker.SetName( aSearchName ); 260 aStartMarker.PutValue( aElement ); 261 262 (*aIter)->Put( aStartMarker, XATTR_LINESTART ); 263 return; 264 } 265 aIter++; 266 } 267 268 // if it is not in our own sets, modify the pool! 269 sal_Bool bFound = sal_False; 270 271 sal_uInt32 nSurrogate; 272 const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 273 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 274 { 275 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 276 if( pItem && pItem->GetName() == aSearchName ) 277 { 278 pItem->PutValue( aElement ); 279 bFound = sal_True; 280 break; 281 } 282 } 283 284 const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 285 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 286 { 287 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 288 if( pItem && pItem->GetName() == aSearchName ) 289 { 290 pItem->PutValue( aElement ); 291 bFound = sal_True; 292 break; 293 } 294 } 295 296 if( bFound ) 297 ImplInsertByName( aName, aElement ); 298 else 299 throw container::NoSuchElementException(); 300 } 301 302 static sal_Bool getByNameFromPool( const String& rSearchName, SfxItemPool* pPool, sal_uInt16 nWhich, uno::Any& rAny ) 303 { 304 NameOrIndex *pItem; 305 const sal_uInt32 nSurrogateCount = pPool ? pPool->GetItemCount2( nWhich ) : 0; 306 for( sal_uInt32 nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ ) 307 { 308 pItem = (NameOrIndex*)pPool->GetItem2( nWhich, nSurrogate ); 309 310 if( pItem && pItem->GetName() == rSearchName ) 311 { 312 pItem->QueryValue( rAny, 0 ); 313 return sal_True; 314 } 315 } 316 317 return sal_False; 318 } 319 320 // XNameAccess 321 uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName ) 322 { 323 OGuard aGuard( Application::GetSolarMutex() ); 324 325 String aName; 326 SvxUnogetInternalNameForItem( XATTR_LINEEND, aApiName, aName ); 327 328 uno::Any aAny; 329 330 if( mpModelPool && aName.Len() != 0 ) 331 { 332 do 333 { 334 const String aSearchName( aName ); 335 if( getByNameFromPool( aSearchName, mpModelPool, XATTR_LINESTART, aAny ) ) 336 break; 337 338 if( getByNameFromPool( aSearchName, mpModelPool, XATTR_LINEEND, aAny ) ) 339 break; 340 341 throw container::NoSuchElementException(); 342 } 343 while(0); 344 } 345 346 return aAny; 347 } 348 349 static void createNamesForPool( SfxItemPool* pPool, sal_uInt16 nWhich, std::set< OUString, comphelper::UStringLess >& rNameSet ) 350 { 351 const sal_uInt32 nSuroCount = pPool->GetItemCount2( nWhich ); 352 sal_uInt32 nSurrogate; 353 354 NameOrIndex* pItem; 355 OUString aName; 356 357 for( nSurrogate = 0; nSurrogate < nSuroCount; nSurrogate++ ) 358 { 359 pItem = (NameOrIndex*)pPool->GetItem2( nWhich, nSurrogate ); 360 361 if( pItem == NULL || pItem->GetName().Len() == 0 ) 362 continue; 363 364 SvxUnogetApiNameForItem( XATTR_LINEEND, pItem->GetName(), aName ); 365 rNameSet.insert( aName ); 366 } 367 } 368 369 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames() 370 { 371 OGuard aGuard( Application::GetSolarMutex() ); 372 373 std::set< OUString, comphelper::UStringLess > aNameSet; 374 375 // search model pool for line starts 376 createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet ); 377 378 // search model pool for line ends 379 createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet ); 380 381 uno::Sequence< OUString > aSeq( aNameSet.size() ); 382 OUString* pNames = aSeq.getArray(); 383 384 std::set< OUString, comphelper::UStringLess >::iterator aIter( aNameSet.begin() ); 385 const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aNameSet.end() ); 386 387 while( aIter != aEnd ) 388 { 389 *pNames++ = *aIter++; 390 } 391 392 return aSeq; 393 } 394 395 sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName ) 396 { 397 OGuard aGuard( Application::GetSolarMutex() ); 398 399 if( aName.getLength() == 0 ) 400 return sal_False; 401 402 String aSearchName; 403 404 NameOrIndex *pItem; 405 406 SvxUnogetInternalNameForItem( XATTR_LINESTART, aName, aSearchName ); 407 sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 408 sal_uInt32 nSurrogate; 409 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 410 { 411 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 412 if( pItem && pItem->GetName() == aSearchName ) 413 return sal_True; 414 } 415 416 SvxUnogetInternalNameForItem( XATTR_LINEEND, aName, aSearchName ); 417 sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 418 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 419 { 420 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 421 if( pItem && pItem->GetName() == aSearchName ) 422 return sal_True; 423 } 424 425 return sal_False; 426 } 427 428 // XElementAccess 429 uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( ) 430 { 431 return ::getCppuType((const drawing::PointSequence*)0); 432 } 433 434 sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( ) 435 { 436 OGuard aGuard( Application::GetSolarMutex() ); 437 438 NameOrIndex *pItem; 439 440 const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0; 441 sal_uInt32 nSurrogate; 442 for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ ) 443 { 444 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate); 445 if( pItem && pItem->GetName().Len() != 0 ) 446 return sal_True; 447 } 448 449 const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0; 450 for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ ) 451 { 452 pItem = (NameOrIndex*)mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate); 453 if( pItem && pItem->GetName().Len() != 0 ) 454 return sal_True; 455 } 456 457 return sal_False; 458 } 459 460 /** 461 * Create a hatchtable 462 */ 463 uno::Reference< uno::XInterface > SAL_CALL SvxUnoMarkerTable_createInstance( SdrModel* pModel ) 464 { 465 return *new SvxUnoMarkerTable(pModel); 466 } 467