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_sfx2.hxx" 26 #include <com/sun/star/embed/VerbDescriptor.hpp> 27 #include <com/sun/star/embed/VerbAttributes.hpp> 28 #include <basic/sbstar.hxx> 29 #include <svl/itempool.hxx> 30 #include <svl/undo.hxx> 31 #include <svtools/itemdel.hxx> 32 #include <svtools/asynclink.hxx> 33 #include <basic/sbx.hxx> 34 35 #include <unotools/undoopt.hxx> 36 37 #ifndef GCC 38 #endif 39 40 #include <sfx2/app.hxx> 41 #include <sfx2/shell.hxx> 42 #include <sfx2/bindings.hxx> 43 #include <sfx2/dispatch.hxx> 44 #include <sfx2/viewfrm.hxx> 45 #include <sfx2/objface.hxx> 46 #include <sfx2/objsh.hxx> 47 #include <sfx2/viewsh.hxx> 48 #include <sfx2/dispatch.hxx> 49 #include "sfxtypes.hxx" 50 #include <sfx2/request.hxx> 51 #include <sfx2/mnumgr.hxx> 52 #include "statcach.hxx" 53 #include <sfx2/msgpool.hxx> 54 55 //==================================================================== 56 57 DBG_NAME(SfxShell) 58 59 //==================================================================== 60 61 TYPEINIT0(SfxShell); 62 63 //==================================================================== 64 typedef SfxSlot* SfxSlotPtr; 65 SV_DECL_PTRARR_DEL( SfxVerbSlotArr_Impl, SfxSlotPtr, 4, 4) 66 SV_IMPL_PTRARR( SfxVerbSlotArr_Impl, SfxSlotPtr); 67 68 using namespace com::sun::star; 69 70 //========================================================================= 71 // SfxShell_Impl 72 //========================================================================= 73 struct SfxShell_Impl: public SfxBroadcaster 74 { 75 String aObjectName;// Name des Sbx-Objects 76 SfxItemArray_Impl aItems; // Datenaustausch auf Item-Basis 77 SfxViewShell* pViewSh; // SfxViewShell falls Shell ViewFrame/ViewShell/SubShell ist 78 SfxViewFrame* pFrame; // Frame, falls <UI-aktiv> 79 SfxRepeatTarget* pRepeatTarget; 80 // SbxObjectRef xParent; 81 sal_Bool bInAppBASIC; 82 sal_Bool bActive; 83 sal_uIntPtr nDisableFlags; 84 sal_uIntPtr nHelpId; 85 svtools::AsynchronLink* pExecuter; 86 svtools::AsynchronLink* pUpdater; 87 SfxVerbSlotArr_Impl aSlotArr; 88 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aVerbList; 89 SfxShell_Impl() : pExecuter( 0 ), pUpdater( 0 ) {} 90 ~SfxShell_Impl() { delete pExecuter; delete pUpdater;} 91 }; 92 93 //==================================================================== 94 #ifdef DBG_UTIL 95 96 String SfxShellIdent_Impl( const SfxShell *pSh ) 97 98 /* [Beschreibung] 99 100 Interne Hilfesfunktion. Liefert einen die SfxShell 'pSh' beschreibenden 101 String zur"uck. Z.B.: SfxApplication[StarWriter] 102 */ 103 104 { 105 String aIdent( pSh->ISA(SfxApplication) ? DEFINE_CONST_UNICODE("SfxApplication") : 106 pSh->ISA(SfxViewFrame) ? DEFINE_CONST_UNICODE("SfxViewFrame") : 107 pSh->ISA(SfxViewShell) ? DEFINE_CONST_UNICODE("SfxViewShell") : 108 pSh->ISA(SfxObjectShell) ? DEFINE_CONST_UNICODE("SfxObjectShell") : DEFINE_CONST_UNICODE("SfxShell") ); 109 aIdent += '['; 110 aIdent += pSh->GetName(); 111 aIdent += ']'; 112 return aIdent; 113 } 114 115 #endif 116 //==================================================================== 117 118 //========================================================================= 119 // SfxShell 120 //========================================================================= 121 122 void __EXPORT SfxShell::EmptyExecStub(SfxShell *, SfxRequest &) 123 { 124 } 125 126 void __EXPORT SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &) 127 { 128 } 129 130 SfxShell::SfxShell() 131 132 /* [Beschreibung] 133 134 Der Konstruktor der Klasse SfxShell initialisierung nur einfache 135 Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt. 136 Daher ist das Anlegen einer SfxShell Instanz sehr billig. 137 */ 138 139 : pImp(0), 140 pPool(0), 141 pUndoMgr(0) 142 { 143 DBG_CTOR(SfxShell, 0); 144 pImp = new SfxShell_Impl; 145 pImp->pViewSh = 0; 146 pImp->pFrame = 0; 147 pImp->pRepeatTarget = 0; 148 pImp->bInAppBASIC = sal_False; 149 pImp->nHelpId = 0L; 150 pImp->bActive = sal_False; 151 pImp->nDisableFlags = 0; 152 } 153 154 //------------------------------------------------------------------------- 155 156 SfxShell::SfxShell( SfxViewShell *pViewSh ) 157 158 /* [Beschreibung] 159 160 Der Konstruktor der Klasse SfxShell initialisierung nur einfache 161 Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt. 162 Daher ist das Anlegen einer SfxShell Instanz sehr billig. 163 */ 164 165 : pImp(0), 166 pPool(0), 167 pUndoMgr(0) 168 { 169 DBG_CTOR(SfxShell, 0); 170 pImp = new SfxShell_Impl; 171 pImp->pViewSh = pViewSh; 172 pImp->pFrame = 0; 173 pImp->pRepeatTarget = 0; 174 pImp->bInAppBASIC = sal_False; 175 pImp->nHelpId = 0L; 176 pImp->bActive = sal_False; 177 } 178 179 //-------------------------------------------------------------------- 180 181 SfxShell::~SfxShell() 182 183 /* [Beschreibung] 184 185 Die Verbindungs zu einem ggf. zugeh"origen SbxObject wird gel"ost. 186 Das SbxObject existiert ggf. weiter, kann aber keine Funktionen 187 mehr ausf"uhren und keine Properties mehr bereitstellen. 188 */ 189 190 { 191 DBG_DTOR(SfxShell, 0); 192 delete pImp; 193 } 194 195 //-------------------------------------------------------------------- 196 197 void SfxShell::SetName( const String &rName ) 198 199 /* [Beschreibung] 200 201 Setzt den Namen des Shell-Objekts. Mit diesem Namen kann die 202 SfxShell-Instanz vom BASIC aus angesprochen werden. 203 */ 204 205 { 206 pImp->aObjectName = rName; 207 } 208 209 //-------------------------------------------------------------------- 210 211 const String& SfxShell::GetName() const 212 213 /* [Beschreibung] 214 215 Liefert den Namen des Shell-Objekts. Mit diesem Namen kann die 216 SfxShell-Instanz vom BASIC aus angesprochen werden. 217 */ 218 219 { 220 return pImp->aObjectName; 221 } 222 223 //-------------------------------------------------------------------- 224 225 SvGlobalName SfxShell::GetGlobalName() const 226 227 /* [Beschreibung] 228 229 Liefert den Global Unique Identifier des Shell-Objekts. Mit diesem 230 Namen kann die SfxShell-Instanz z.B. via OLE Automation angesprochen 231 werden, bzw. in der Registration-Database gefunden werden. 232 */ 233 234 { 235 return SvGlobalName(); 236 } 237 238 //-------------------------------------------------------------------- 239 240 SfxDispatcher* SfxShell::GetDispatcher() const 241 242 /* [Beschreibung] 243 244 Diese Methode liefert einen Pointer auf den <SfxDispatcher>, in 245 dem die SfxShell gerade <UI-aktiv> ist bzw. einen 0-Pointer, wenn 246 sie gerade nicht UI-aktiv ist. 247 248 Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des 249 Methodenaufrufs g"ultig. 250 */ 251 252 { 253 return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0; 254 } 255 256 //-------------------------------------------------------------------- 257 258 SfxViewShell* SfxShell::GetViewShell() const 259 260 /* [Beschreibung] 261 262 Liefert bei SubShells die SfxViewShell, in der sie liegen. Sonst und 263 falls nicht vom App-Entwickler angegeben liefert diese Methode 0. 264 */ 265 266 { 267 return pImp->pViewSh; 268 } 269 270 //-------------------------------------------------------------------- 271 272 SfxViewFrame* SfxShell::GetFrame() const 273 274 /* [Beschreibung] 275 276 Diese Methode liefert einen Pointer auf den <SfxViewFrame>, dem diese 277 SfxShell-Instanz zugeordnet ist oder in dem sie zur Zeit <UI-aktiv> ist. 278 Ein 0-Pointer wird geliefert, wenn diese SfxShell-OInstanz gerade nicht 279 UI-aktiv ist und auch keinem SfxViewFrame fest zugeordnet ist. 280 281 Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des 282 Methodenaufrufs g"ultig. 283 284 285 [Anmerkung] 286 287 Nur Instanzen von Subklasse von SfxApplication und SfxObjectShell sollten 288 hier einen 0-Pointer liefern. Ansonsten liegt ein Fehler im Anwendungs- 289 programm vor (falscher Ctor von SfxShell gerufen). 290 291 292 [Querverweise] 293 294 <SfxViewShell::GetViewFrame()const> 295 */ 296 297 { 298 if ( pImp->pFrame ) 299 return pImp->pFrame; 300 if ( pImp->pViewSh ) 301 return pImp->pViewSh->GetViewFrame(); 302 return 0; 303 } 304 305 //-------------------------------------------------------------------- 306 307 const SfxPoolItem* SfxShell::GetItem 308 ( 309 sal_uInt16 nSlotId // Slot-Id des zu erfragenden <SfxPoolItem>s 310 ) const 311 312 /* [Beschreibung] 313 314 Mit dieser Methode kann auf beliebige Objekte von Subklassen von 315 <SfxPoolItem> zugegriffen werden. Diese Austauschtechnik wird ben"otigt, 316 wenn z.B. spezielle <SfxToolBoxControl> Subklassen Zugriff auf 317 bestimmte Daten z.B. der <SfxObjectShell> ben"otigen. 318 319 Die zur"uckgelieferte Instanz geh"ort der jeweilige SfxShell und 320 darf nur im unmittelbaren Kontext des Methodenaufrufs verwendet werden. 321 322 323 [Querverweise] 324 325 <SfxShell::PutItem(const SfxPoolItem&)> 326 <SfxShell::RemoveItem(sal_uInt16)> 327 */ 328 329 { 330 for ( sal_uInt16 nPos = 0; nPos < pImp->aItems.Count(); ++nPos ) 331 if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId ) 332 return pImp->aItems.GetObject(nPos); 333 return 0; 334 } 335 336 //-------------------------------------------------------------------- 337 338 void SfxShell::RemoveItem 339 ( 340 sal_uInt16 nSlotId // Slot-Id des zu l"oschenden <SfxPoolItem>s 341 ) 342 343 /* [Beschreibung] 344 345 Mit dieser Methode k"onnen die allgemein zur Verf"ugung gestellten 346 Instanzen von Subklassen von <SfxPoolItem> aus der SfxShell entfernt 347 werden. 348 349 Die gespeicherte Instanz wird gel"oscht. 350 351 352 [Querverweise] 353 354 <SfxShell::PutItem(const SfxPoolItem&)> 355 <SfxShell::GetItem(sal_uInt16)> 356 */ 357 358 { 359 for ( sal_uInt16 nPos = 0; nPos < pImp->aItems.Count(); ++nPos ) 360 if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId ) 361 { 362 // Item entfernen und l"oschen 363 SfxPoolItem *pItem = pImp->aItems.GetObject(nPos); 364 delete pItem; 365 pImp->aItems.Remove(nPos); 366 367 // falls aktiv Bindings benachrichtigen 368 SfxDispatcher *pDispat = GetDispatcher(); 369 if ( pDispat ) 370 { 371 SfxVoidItem aVoid( nSlotId ); 372 pDispat->GetBindings()->Broadcast( SfxPoolItemHint( &aVoid ) ); 373 } 374 } 375 } 376 377 //-------------------------------------------------------------------- 378 379 void SfxShell::PutItem 380 ( 381 const SfxPoolItem& rItem /* Instanz, von der eine Kopie erstellt wird, 382 die in der SfxShell in einer Liste 383 gespeichert wird. */ 384 ) 385 386 /* [Beschreibung] 387 388 Mit dieser Methode k"onnen beliebige Objekte von Subklassen von 389 <SfxPoolItem> zur Verf"ugung gestellt werden. Diese Austauschtechnik 390 wird ben"otigt, wenn z.B. spezielle <SfxToolBoxControl> Subklassen 391 Zugriff auf bestimmte Daten z.B. der <SfxObjectShell> ben"otigen. 392 393 Falls ein SfxPoolItem mit derselben Slot-Id exisitert, wird dieses 394 automatisch gel"oscht. 395 396 397 [Querverweise] 398 399 <SfxShell::RemoveItem(sal_uInt16)> 400 <SfxShell::GetItem(sal_uInt16)> 401 */ 402 403 { 404 DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" ); 405 DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ), 406 "items with Which-Ids aren't allowed here" ); 407 408 // MSC auf WNT/W95 machte hier Mist, Vorsicht bei Umstellungen 409 const SfxPoolItem *pItem = rItem.Clone(); 410 SfxPoolItemHint aItemHint( (SfxPoolItem*) pItem ); 411 const sal_uInt16 nWhich = rItem.Which(); 412 SfxPoolItem **ppLoopItem = (SfxPoolItem**) pImp->aItems.GetData(); 413 sal_uInt16 nPos; 414 for ( nPos = 0; nPos < pImp->aItems.Count(); ++nPos, ++ppLoopItem ) 415 { 416 if ( (*ppLoopItem)->Which() == nWhich ) 417 { 418 // Item austauschen 419 delete *ppLoopItem; 420 pImp->aItems.Remove(nPos); 421 pImp->aItems.Insert( (SfxPoolItemPtr) pItem, nPos ); 422 423 // falls aktiv Bindings benachrichtigen 424 SfxDispatcher *pDispat = GetDispatcher(); 425 if ( pDispat ) 426 { 427 SfxBindings* pBindings = pDispat->GetBindings(); 428 pBindings->Broadcast( aItemHint ); 429 sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId(); 430 SfxStateCache* pCache = pBindings->GetStateCache( nSlotId ); 431 if ( pCache ) 432 { 433 pCache->SetState( SFX_ITEM_AVAILABLE, pItem->Clone(), sal_True ); 434 pCache->SetCachedState( sal_True ); 435 } 436 } 437 return; 438 } 439 } 440 441 Broadcast( aItemHint ); 442 pImp->aItems.Insert((SfxPoolItemPtr)pItem, nPos ); 443 } 444 445 //-------------------------------------------------------------------- 446 447 SfxInterface* SfxShell::GetInterface() const 448 449 /* [Beschreibung] 450 451 Mit dieser virtuellen Methode, die durch das Makro <SFX_DECL_INTERFACE> 452 von jeder Subclass mit eigenen Slots automatisch "uberladen wird, kann 453 auf die zu der Subklasse geh"orende <SfxInterface>-Instanz zugegriffen 454 werden. 455 456 Die Klasse SfxShell selbst hat noch kein eigenes SfxInterface 457 (keine Slots), daher wird ein 0-Pointer zur"uckgeliefert. 458 */ 459 460 { 461 return GetStaticInterface(); 462 } 463 464 //-------------------------------------------------------------------- 465 466 SfxBroadcaster* SfxShell::GetBroadcaster() 467 468 /* [Beschreibung] 469 470 Liefert einen SfxBroadcaster f"ur diese SfxShell-Instanz bis die 471 Klasse SfxShell von SfxBroadcaster abgeleitet ist. 472 */ 473 474 { 475 return pImp; 476 } 477 478 //-------------------------------------------------------------------- 479 480 ::svl::IUndoManager* SfxShell::GetUndoManager() 481 482 /* [Beschreibung] 483 484 Jede Subclass von SfxShell kann "uber einen <SfxUndoManager> verf"ugen. 485 Dieser kann in den abgeleiteten Klasse mit <SfxShell:SetUndoManager()> 486 gesetzt werden. 487 488 Die Klasse SfxShell selbst hat noch keinen SfxUndoManager, es wird 489 daher ein 0-Pointer zur"uckgeliefert. 490 */ 491 492 { 493 return pUndoMgr; 494 } 495 496 //-------------------------------------------------------------------- 497 498 void SfxShell::SetUndoManager( ::svl::IUndoManager *pNewUndoMgr ) 499 500 /* [Beschreibung] 501 502 Setzt einen <SfxUndoManager> f"ur diese <SfxShell> Instanz. F"ur das 503 Undo wird immer nur der Undo-Manager an der jeweils oben auf dem 504 Stack des <SfxDispatcher> liegenden SfxShell verwendet. 505 506 Am "ubergebenen <SfxUndoManager> wird automatisch die aktuelle 507 Max-Undo-Action-Count Einstellung aus den Optionen gesetzt. 508 509 'pNewUndoMgr' mu\s bis zum Dtor dieser SfxShell-Instanz oder bis 510 zum n"achsten 'SetUndoManager()' existieren. 511 */ 512 513 { 514 OSL_ENSURE( ( pUndoMgr == NULL ) || ( pNewUndoMgr == NULL ) || ( pUndoMgr == pNewUndoMgr ), 515 "SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" ); 516 // there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which 517 // caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really 518 // a supported scenario (/me thinks it is not), then we would need to notify all such clients instances. 519 520 pUndoMgr = pNewUndoMgr; 521 if ( pUndoMgr ) 522 pUndoMgr->SetMaxUndoActionCount( (sal_uInt16) SvtUndoOptions().GetUndoCount() ); 523 } 524 525 //-------------------------------------------------------------------- 526 527 SfxRepeatTarget* SfxShell::GetRepeatTarget() const 528 529 /* [Beschreibung] 530 531 Liefert einen Pointer auf die <SfxRepeatTarget>-Instanz, die 532 als RepeatTarget bei SID_REPEAT verwendet wird, wenn der 533 von dieser SfxShell gelieferte <SfxUndoManager> angesprochen wird. 534 Der R"uckgabewert kann 0 sein. 535 536 537 [Anmerkung] 538 539 Eine Ableitung von <SfxShell> oder einer ihrer Subklassen von 540 <SfxRepeatTarget> ist nicht zu empfehlen, da Compiler-Fehler 541 provoziert werden (wegen Call-to-Pointer-to-Member-Function to 542 subclass). 543 */ 544 545 { 546 return pImp->pRepeatTarget; 547 } 548 549 //-------------------------------------------------------------------- 550 551 void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget ) 552 553 /* [Beschreibung] 554 555 Setzt den die <SfxRepeatTarget>-Instanz, die bei SID_REPEAT als 556 RepeatTarget verwendet wird, wenn der von dieser SfxShell gelieferte 557 <SfxUndoManager> angesprochen wird. Durch 'pTarget==0' wird SID_REPEAT 558 f"ur diese SfxShell disabled. Die Instanz '*pTarget' mu\s so lange 559 leben, wie sie angemeldet ist. 560 561 562 [Anmerkung] 563 564 Eine Ableitung von <SfxShell> oder einer ihrer Subklassen von 565 <SfxRepeatTarget> ist nicht zu empfehlen, da Compiler-Fehler 566 provoziert werden (wegen Call-to-Pointer-to-Member-Function to 567 subclass). 568 */ 569 570 { 571 pImp->pRepeatTarget = pTarget; 572 } 573 574 //-------------------------------------------------------------------- 575 576 void SfxShell::Invalidate 577 ( 578 sal_uInt16 nId /* Zu invalidierende Slot-Id oder Which-Id. 579 Falls diese 0 ist (default), werden 580 alle z.Zt. von dieser Shell bedienten 581 Slot-Ids invalidiert. */ 582 ) 583 584 /* [Beschreibung] 585 586 Mit dieser Methode k"onnen Slots der Subclasses "uber die Slot-Id 587 oder alternativ "uber die Which-Id invalidiert werden. Slot-Ids, 588 die von der Subclass ererbt sind, werden ebenfalls invalidert. 589 590 [Querverweise] 591 <SfxBindings::Invalidate(sal_uInt16)> 592 <SfxBindings::InvalidateAll(sal_Bool)> 593 */ 594 595 { 596 if ( !GetViewShell() ) 597 { 598 DBG_ERROR( "wrong Invalidate method called!" ); 599 return; 600 } 601 602 Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId ); 603 } 604 605 void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId ) 606 { 607 if ( nId == 0 ) 608 { 609 rBindings.InvalidateShell( *this, sal_False ); 610 } 611 else 612 { 613 const SfxInterface *pIF = GetInterface(); 614 do 615 { 616 const SfxSlot *pSlot = pIF->GetSlot(nId); 617 if ( pSlot ) 618 { 619 // bei Enum-Slots ist der Master-Slot zu invalidieren 620 if ( SFX_KIND_ENUM == pSlot->GetKind() ) 621 pSlot = pSlot->GetLinkedSlot(); 622 623 // den Slot selbst und ggf. auch alle Slave-Slots invalidieren 624 rBindings.Invalidate( pSlot->GetSlotId() ); 625 for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot(); 626 pSlave && pIF->ContainsSlot_Impl( pSlave ) && 627 pSlave->GetLinkedSlot() == pSlot; 628 ++pSlave ) 629 rBindings.Invalidate( pSlave->GetSlotId() ); 630 631 return; 632 } 633 634 pIF = pIF->GetGenoType(); 635 } 636 637 while ( pIF ); 638 639 DBG_WARNING( "W3: invalidating slot-id unknown in shell" ); 640 } 641 } 642 643 //-------------------------------------------------------------------- 644 645 void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI ) 646 647 /* [Beschreibung] 648 649 Diese Methode steuert die Aktivierung der SfxShell-Instanz. Zun"achst 650 wird durch Aufruf der virtuellen Methode <SfxShell::Activate(sal_Bool)> 651 der Subclass die M"oglichkeit gegeben, auf das Event zu reagieren. 652 653 Bei bMDI == TRUE wird das zugeh"orige SbxObject 'scharfgeschaltet', 654 so da\s Methoden des Objekts unqualifiziert (ohne den Namen des Objekts) 655 vom BASIC gefunden werden. 656 */ 657 658 { 659 #ifdef DBG_UTIL 660 const SfxInterface *p_IF = GetInterface(); 661 if ( !p_IF ) 662 return; 663 #endif 664 #ifdef DBG_UTIL_VB 665 String aMsg("SfxShell::DoActivate() "); 666 aMsg += (long)this; 667 aMsg += " "; 668 aMsg += GetInterface()->GetName(); 669 aMsg += " bMDI "; 670 if ( bMDI ) aMsg += "MDI"; 671 DbgTrace( aMsg.GetBuffer() ); 672 #endif 673 674 if ( bMDI ) 675 { 676 // Frame merken, in dem aktiviert wird 677 pImp->pFrame = pFrame; 678 pImp->bActive = sal_True; 679 } 680 681 // Subklasse benachrichtigen 682 Activate(bMDI); 683 } 684 685 //-------------------------------------------------------------------- 686 687 void SfxShell::DoDeactivate_Impl( SfxViewFrame *pFrame, sal_Bool bMDI ) 688 689 /* [Beschreibung] 690 691 Diese Methode steuert die Deaktivierung der SfxShell-Instanz. Bei 692 bMDI == TRUE wird zun"achst das SbxObject in einen Status versetzt, 693 so da\s Methoden vom BASIC aus nur noch qualifiziert gerufen werden 694 k"onnen. 695 696 Dann erh"alt in jedem Fall die Subclass durch Aufruf der virtuellen 697 Methode <SfxShell::Deactivate(sal_Bool)> die M"oglichkeit auf das Event 698 zu reagieren. 699 */ 700 701 { 702 #ifdef DBG_UTIL 703 const SfxInterface *p_IF = GetInterface(); 704 if ( !p_IF ) 705 return; 706 #endif 707 #ifdef DBG_UTIL_VB 708 String aMsg("SfxShell::DoDeactivate()"); 709 aMsg += (long)this; 710 aMsg += " "; 711 aMsg += GetInterface()->GetName(); 712 aMsg += " bMDI "; 713 if ( bMDI ) aMsg += "MDI"; 714 DbgTrace( aMsg.GetBuffer() ); 715 #endif 716 717 // nur wenn er vom Frame kommt (nicht z.B. pop der BASIC-IDE vom AppDisp) 718 if ( bMDI && pImp->pFrame == pFrame ) 719 { 720 // austragen 721 pImp->pFrame = 0; 722 pImp->bActive = sal_False; 723 } 724 725 // Subklasse benachrichtigen 726 Deactivate(bMDI); 727 } 728 729 //-------------------------------------------------------------------- 730 731 sal_Bool SfxShell::IsActive() const 732 { 733 return pImp->bActive; 734 } 735 736 //-------------------------------------------------------------------- 737 738 void SfxShell::Activate 739 ( 740 sal_Bool /*bMDI*/ /* TRUE 741 der <SfxDispatcher>, auf dem die SfxShell sich 742 befindet, ist aktiv geworden oder die SfxShell 743 Instanz wurde auf einen aktiven SfxDispatcher 744 gepusht. (vergl. SystemWindow::IsMDIActivate()) 745 746 FALSE 747 das zum <SfxViewFrame>, auf dessen SfxDispatcher 748 sich die SfxShell Instanz befindet, wurde 749 aktiviert. 750 (z.B. durch einen geschlossenen Dialog) */ 751 ) 752 753 /* [Beschreibung] 754 755 Virtuelle Methode, die beim Aktivieren der SfxShell Instanz gerufen 756 wird, um den Subclasses die Gelegenheit zu geben, auf das Aktivieren 757 zu reagieren. 758 759 Die Basisimplementation ist leer und braucht nicht gerufen zu werden. 760 761 762 [Querverweise] 763 StarView SystemWindow::Activate(sal_Bool) 764 */ 765 766 { 767 } 768 769 //-------------------------------------------------------------------- 770 771 void SfxShell::Deactivate 772 ( 773 sal_Bool /*bMDI*/ /* TRUE 774 der <SfxDispatcher>, auf dem die SfxShell sich 775 befindet, ist inaktiv geworden oder die SfxShell 776 Instanz wurde auf einen aktiven SfxDispatcher 777 gepoppt. (vergl. SystemWindow::IsMDIActivate()) 778 779 FALSE 780 das zum <SfxViewFrame>, auf dessen SfxDispatcher 781 sich die SfxShell Instanz befindet, wurde 782 deaktiviert. (z.B. durch einen Dialog) */ 783 784 ) 785 786 /* [Beschreibung] 787 788 Virtuelle Methode, die beim Deaktivieren der SfxShell Instanz gerufen 789 wird, um den Subclasses die Gelegenheit zu geben, auf das Deaktivieren 790 zu reagieren. 791 792 Die Basisimplementation ist leer und braucht nicht gerufen zu werden. 793 794 795 [Querverweise] 796 StarView SystemWindow::Dectivate(sal_Bool) 797 */ 798 799 { 800 } 801 802 void SfxShell::ParentActivate 803 ( 804 ) 805 806 /* [Beschreibung] 807 808 Ein Parent des <SfxDispatcher>, auf dem die SfxShell sich befindet, 809 ist aktiv geworden, oder die SfxShell Instanz wurde auf einen 810 <SfxDispatcher> gepusht, dessen parent aktiv ist. 811 812 Die Basisimplementation ist leer und braucht nicht gerufen zu werden. 813 814 [Querverweise] 815 SfxShell::Activate() 816 */ 817 { 818 } 819 820 //-------------------------------------------------------------------- 821 822 void SfxShell::ParentDeactivate 823 ( 824 ) 825 826 /* [Beschreibung] 827 828 Der aktive Parent des <SfxDispatcher>, auf dem die SfxShell sich befindet, 829 ist deaktiviert worden. 830 831 Die Basisimplementation ist leer und braucht nicht gerufen zu werden. 832 833 [Querverweise] 834 SfxShell::Deactivate() 835 */ 836 { 837 } 838 839 //-------------------------------------------------------------------- 840 841 ResMgr* SfxShell::GetResMgr() const 842 843 /* [Beschreibung] 844 845 Diese Methode liefert den ResMgr der <Resource-DLL>, die von der 846 SfxShell-Instanz verwendet wird. Ist dies ein 0-Pointer, so 847 ist der aktuelle Resource-Manager zu verwenden. 848 */ 849 850 { 851 return GetInterface()->GetResMgr(); 852 } 853 854 //-------------------------------------------------------------------- 855 856 bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot ) 857 858 /* [Beschreibung] 859 860 Diese Methode stellt durch Aufruf der Statusfunktion fest, 861 ob 'rSlot' aktuell ausgef"uhrt werden kann. 862 */ 863 { 864 // Slot-Status holen 865 SfxItemPool &rPool = GetPool(); 866 const sal_uInt16 nId = rSlot.GetWhich( rPool ); 867 SfxItemSet aSet(rPool, nId, nId); 868 SfxStateFunc pFunc = rSlot.GetStateFnc(); 869 CallState( pFunc, aSet ); 870 return aSet.GetItemState(nId) != SFX_ITEM_DISABLED; 871 } 872 873 //-------------------------------------------------------------------- 874 875 long ShellCall_Impl( void* pObj, void* pArg ) 876 { 877 ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L ); 878 return 0; 879 } 880 881 /* [Beschreibung] 882 Asynchrones ExecuteSlot fuer das RELOAD 883 */ 884 885 //-------------------------------------------------------------------- 886 const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, sal_Bool bAsync ) 887 { 888 if( !bAsync ) 889 return ExecuteSlot( rReq, (SfxInterface*)0L ); 890 else 891 { 892 if( !pImp->pExecuter ) 893 pImp->pExecuter = new svtools::AsynchronLink( 894 Link( this, ShellCall_Impl ) ); 895 pImp->pExecuter->Call( new SfxRequest( rReq ) ); 896 return 0; 897 } 898 } 899 900 const SfxPoolItem* SfxShell::ExecuteSlot 901 ( 902 SfxRequest &rReq, // der weiterzuleitende <SfxRequest> 903 const SfxInterface* pIF // default = 0 bedeutet virtuell besorgen 904 ) 905 906 /* [Beschreibung] 907 908 Diese Methode erm"oglicht das Weiterleiten eines <SfxRequest> an 909 die angegebene Basis-<SfxShell>. 910 911 912 [Beispiel] 913 914 In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT 915 abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken 916 eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden. 917 918 Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die 919 Execute-Methode enth"alt dann skizziert: 920 921 void SubViewShell::Exec( SfxRequest &rReq ) 922 { 923 if ( rReq.GetSlot() == SID_PRINTDOCDIRECT ) 924 { 925 'dialog' 926 if ( 'condition' ) 927 ExecuteSlot( rReq, SfxViewShell::GetInterface() ); 928 } 929 } 930 931 Es braucht i.d.R. kein rReq.Done() gerufen zu werden, da das bereits 932 die Implementierung der SfxViewShell erledigt bzw. abgebrochen wurde. 933 934 935 [Querverweise] 936 937 <SfxShell::GetSlotState(sal_uInt16,const SfxInterface*,SfxItemSet*)> 938 */ 939 940 { 941 if ( !pIF ) 942 pIF = GetInterface(); 943 944 sal_uInt16 nSlot = rReq.GetSlot(); 945 const SfxSlot* pSlot = NULL; 946 if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END ) 947 pSlot = GetVerbSlot_Impl(nSlot); 948 if ( !pSlot ) 949 pSlot = pIF->GetSlot(nSlot); 950 DBG_ASSERT( pSlot, "slot not supported" ); 951 952 SfxExecFunc pFunc = pSlot->GetExecFnc(); 953 if ( pFunc ) 954 CallExec( pFunc, rReq ); 955 956 return rReq.GetReturnValue(); 957 } 958 959 //-------------------------------------------------------------------- 960 961 const SfxPoolItem* SfxShell::GetSlotState 962 ( 963 sal_uInt16 nSlotId, // Slot-Id des zu befragenden Slots 964 const SfxInterface* pIF, // default = 0 bedeutet virtuell besorgen 965 SfxItemSet* pStateSet // SfxItemSet der Slot-State-Methode 966 ) 967 968 /* [Beschreibung] 969 970 Diese Methode liefert den Status des Slots mit der angegebenen Slot-Id 971 "uber das angegebene Interface. 972 973 Ist der Slot disabled oder in dieser SfxShell (und deren Parent-Shells) 974 nicht bekannt, wird ein 0-Pointer zur"uckgeliefert. 975 976 Hat der Slot keinen Status, wird ein SfxVoidItem zur"uckgeliefert. 977 978 Der Status wird bei pStateSet != 0 gleich in diesem Set gesetzt, so 979 da\s <SfxShell>-Subklassen Slots-"uberladen und auch bei der 980 Status-Methode die Basis-Implementierung rufen k"onnen. 981 982 983 [Beispiel] 984 985 In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT 986 abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken 987 eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden. 988 989 Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die 990 Status-Methode enth"alt dann skizziert: 991 992 void SubViewShell::PrintState( SfxItemSet &rState ) 993 { 994 if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN ) 995 GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(), 996 &rState ); 997 ... 998 } 999 1000 1001 [Querverweise] 1002 1003 <SfxShell::ExecuteSlot(SfxRequest&)> 1004 */ 1005 1006 { 1007 // Slot am angegebenen Interface besorgen 1008 if ( !pIF ) 1009 pIF = GetInterface(); 1010 SfxItemState eState; 1011 SfxItemPool &rPool = GetPool(); 1012 1013 const SfxSlot* pSlot = NULL; 1014 if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END ) 1015 pSlot = GetVerbSlot_Impl(nSlotId); 1016 if ( !pSlot ) 1017 pSlot = pIF->GetSlot(nSlotId); 1018 if ( pSlot ) 1019 // ggf. auf Which-Id mappen 1020 nSlotId = pSlot->GetWhich( rPool ); 1021 1022 // Item und Item-Status besorgen 1023 const SfxPoolItem *pItem = NULL; 1024 SfxItemSet aSet( rPool, nSlotId, nSlotId ); // pItem stirbt sonst zu fr"uh 1025 if ( pSlot ) 1026 { 1027 // Status-Methode rufen 1028 SfxStateFunc pFunc = pSlot->GetStateFnc(); 1029 if ( pFunc ) 1030 CallState( pFunc, aSet ); 1031 eState = aSet.GetItemState( nSlotId, sal_True, &pItem ); 1032 1033 // ggf. Default-Item besorgen 1034 if ( eState == SFX_ITEM_DEFAULT ) 1035 { 1036 if ( SfxItemPool::IsWhich(nSlotId) ) 1037 pItem = &rPool.GetDefaultItem(nSlotId); 1038 else 1039 eState = SFX_ITEM_DONTCARE; 1040 } 1041 } 1042 else 1043 eState = SFX_ITEM_UNKNOWN; 1044 1045 // Item und Item-Status auswerten und ggf. in pStateSet mitpflegen 1046 SfxPoolItem *pRetItem = 0; 1047 if ( eState <= SFX_ITEM_DISABLED ) 1048 { 1049 if ( pStateSet ) 1050 pStateSet->DisableItem(nSlotId); 1051 return 0; 1052 } 1053 else if ( eState == SFX_ITEM_DONTCARE ) 1054 { 1055 if ( pStateSet ) 1056 pStateSet->ClearItem(nSlotId); 1057 pRetItem = new SfxVoidItem(0); 1058 } 1059 else 1060 { 1061 if ( pStateSet && pStateSet->Put( *pItem ) ) 1062 return &pStateSet->Get( pItem->Which() ); 1063 pRetItem = pItem->Clone(); 1064 } 1065 DeleteItemOnIdle(pRetItem); 1066 1067 return pRetItem; 1068 } 1069 1070 //-------------------------------------------------------------------- 1071 1072 SFX_EXEC_STUB(SfxShell, VerbExec) 1073 SFX_STATE_STUB(SfxShell, VerbState) 1074 1075 void SfxShell::SetVerbs(const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs) 1076 { 1077 SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this); 1078 1079 DBG_ASSERT(pViewSh, "SetVerbs nur an der ViewShell aufrufen!"); 1080 if ( !pViewSh ) 1081 return; 1082 1083 // Zun"achst alle Statecaches dirty machen, damit keiner mehr versucht, 1084 // die Slots zu benutzen 1085 { 1086 SfxBindings *pBindings = 1087 pViewSh->GetViewFrame()->GetDispatcher()->GetBindings(); 1088 sal_uInt16 nCount = pImp->aSlotArr.Count(); 1089 for (sal_uInt16 n1=0; n1<nCount ; n1++) 1090 { 1091 sal_uInt16 nId = SID_VERB_START + n1; 1092 pBindings->Invalidate(nId, sal_False, sal_True); 1093 } 1094 } 1095 1096 sal_uInt16 nr=0; 1097 for (sal_Int32 n=0; n<aVerbs.getLength(); n++) 1098 { 1099 sal_uInt16 nSlotId = SID_VERB_START + nr++; 1100 DBG_ASSERT(nSlotId <= SID_VERB_END, "Zuviele Verben!"); 1101 if (nSlotId > SID_VERB_END) 1102 break; 1103 1104 SfxSlot *pNewSlot = new SfxSlot; 1105 pNewSlot->nSlotId = nSlotId; 1106 pNewSlot->nGroupId = 0; 1107 1108 // Verb-Slots m"ussen asynchron ausgef"uhrt werden, da sie w"ahrend 1109 // des Ausf"uhrens zerst"ort werden k"onnten 1110 pNewSlot->nFlags = SFX_SLOT_ASYNCHRON | SFX_SLOT_CONTAINER; 1111 pNewSlot->nMasterSlotId = 0; 1112 pNewSlot->nValue = 0; 1113 pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec); 1114 pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState); 1115 pNewSlot->pType = 0; HACK(SFX_TYPE(SfxVoidItem)) 1116 pNewSlot->pName = U2S(aVerbs[n].VerbName); 1117 pNewSlot->pLinkedSlot = 0; 1118 pNewSlot->nArgDefCount = 0; 1119 pNewSlot->pFirstArgDef = 0; 1120 pNewSlot->pUnoName = 0; 1121 1122 if (pImp->aSlotArr.Count()) 1123 { 1124 SfxSlot *pSlot = (pImp->aSlotArr)[0]; 1125 pNewSlot->pNextSlot = pSlot->pNextSlot; 1126 pSlot->pNextSlot = pNewSlot; 1127 } 1128 else 1129 pNewSlot->pNextSlot = pNewSlot; 1130 1131 pImp->aSlotArr.Insert(pNewSlot, (sal_uInt16) n); 1132 } 1133 1134 pImp->aVerbList = aVerbs; 1135 1136 if (pViewSh) 1137 { 1138 // Der Status von SID_OBJECT wird im Controller direkt an der Shell 1139 // abgeholt, es reicht also, ein neues StatusUpdate anzuregen 1140 SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()-> 1141 GetBindings(); 1142 pBindings->Invalidate( SID_OBJECT, sal_True, sal_True ); 1143 } 1144 } 1145 1146 //-------------------------------------------------------------------- 1147 1148 const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& SfxShell::GetVerbs() const 1149 { 1150 return pImp->aVerbList; 1151 } 1152 1153 //-------------------------------------------------------------------- 1154 1155 void SfxShell::VerbExec(SfxRequest& rReq) 1156 { 1157 sal_uInt16 nId = rReq.GetSlot(); 1158 SfxViewShell *pViewShell = GetViewShell(); 1159 if ( pViewShell ) 1160 { 1161 sal_Bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly(); 1162 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aList = pViewShell->GetVerbs(); 1163 for (sal_Int32 n=0, nVerb=0; n<aList.getLength(); n++) 1164 { 1165 // check for ReadOnly verbs 1166 if ( bReadOnly && !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) ) 1167 continue; 1168 1169 // check for verbs that shouldn't appear in the menu 1170 if ( !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) ) 1171 continue; 1172 1173 if (nId == SID_VERB_START + nVerb++) 1174 { 1175 pViewShell->DoVerb(aList[n].VerbID); 1176 rReq.Done(); 1177 return; 1178 } 1179 } 1180 } 1181 } 1182 1183 //-------------------------------------------------------------------- 1184 1185 void SfxShell::VerbState(SfxItemSet& ) 1186 { 1187 } 1188 1189 //-------------------------------------------------------------------- 1190 1191 const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const 1192 { 1193 com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > rList = pImp->aVerbList; 1194 1195 DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Falsche VerbId!"); 1196 sal_uInt16 nIndex = nId - SID_VERB_START; 1197 DBG_ASSERT(nIndex < rList.getLength(),"Falsche VerbId!"); 1198 1199 if (nIndex < rList.getLength()) 1200 return pImp->aSlotArr[nIndex]; 1201 else 1202 return 0; 1203 } 1204 1205 //-------------------------------------------------------------------- 1206 1207 void SfxShell::SetHelpId(sal_uIntPtr nId) 1208 { 1209 pImp->nHelpId = nId; 1210 } 1211 1212 //-------------------------------------------------------------------- 1213 1214 sal_uIntPtr SfxShell::GetHelpId() const 1215 { 1216 return pImp->nHelpId; 1217 } 1218 1219 //-------------------------------------------------------------------- 1220 1221 SfxObjectShell* SfxShell::GetObjectShell() 1222 { 1223 if ( GetViewShell() ) 1224 return GetViewShell()->GetViewFrame()->GetObjectShell(); 1225 else 1226 return NULL; 1227 } 1228 1229 //-------------------------------------------------------------------- 1230 1231 sal_Bool SfxShell::HasUIFeature( sal_uInt32 ) 1232 { 1233 return sal_False; 1234 } 1235 1236 long DispatcherUpdate_Impl( void*, void* pArg ) 1237 { 1238 ((SfxDispatcher*) pArg)->Update_Impl( sal_True ); 1239 ((SfxDispatcher*) pArg)->GetBindings()->InvalidateAll(sal_False); 1240 return 0; 1241 } 1242 1243 void SfxShell::UIFeatureChanged() 1244 { 1245 SfxViewFrame *pFrame = GetFrame(); 1246 if ( pFrame && pFrame->IsVisible() ) 1247 { 1248 // Auch dann Update erzwingen, wenn Dispatcher schon geupdated ist, 1249 // sonst bleibt evtl. irgendwas in den gebunkerten Tools stecken. 1250 // Asynchron aufrufen, um Rekursionen zu vermeiden 1251 if ( !pImp->pUpdater ) 1252 pImp->pUpdater = new svtools::AsynchronLink( Link( this, DispatcherUpdate_Impl ) ); 1253 1254 // Mehrfachaufrufe gestattet 1255 pImp->pUpdater->Call( pFrame->GetDispatcher(), sal_True ); 1256 } 1257 } 1258 1259 void SfxShell::SetDisableFlags( sal_uIntPtr nFlags ) 1260 { 1261 pImp->nDisableFlags = nFlags; 1262 } 1263 1264 sal_uIntPtr SfxShell::GetDisableFlags() const 1265 { 1266 return pImp->nDisableFlags; 1267 } 1268 1269 SfxItemSet* SfxShell::CreateItemSet( sal_uInt16 ) 1270 { 1271 return NULL; 1272 } 1273 1274 void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& ) 1275 { 1276 } 1277 1278 void SfxShell::SetViewShell_Impl( SfxViewShell* pView ) 1279 { 1280 pImp->pViewSh = pView; 1281 } 1282 1283 1284 1285