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 <svl/itempool.hxx> 27 #ifndef GCC 28 #endif 29 30 #include <sfx2/ctrlitem.hxx> 31 #include <sfx2/bindings.hxx> 32 #include <sfx2/dispatch.hxx> 33 #include <sfx2/msgpool.hxx> 34 #include "statcach.hxx" 35 #include <sfx2/viewfrm.hxx> 36 37 //==================================================================== 38 39 DBG_NAME(SfxControllerItem); 40 41 //-------------------------------------------------------------------- 42 #ifdef DBG_UTIL 43 44 void SfxControllerItem::CheckConfigure_Impl( sal_uIntPtr nType ) 45 { 46 // echter Slot? (also kein Separator etc.) 47 if ( !nId ) 48 return; 49 50 // ist die Id "uberhaupt in 'nType' konfigurierbar? 51 const SfxSlot *pSlot = SFX_SLOTPOOL().GetSlot(nId); 52 DBG_ASSERTWARNING( pSlot, "SfxControllerItem: binding not existing slot" ); 53 if ( pSlot && !pSlot->IsMode(nType) ) 54 { 55 DBG_WARNING( "SfxControllerItem: slot without ...Config-flag" ); 56 DbgOutf( "SfxControllerItem: Config-flag missing at SID %5d", 57 pSlot->GetSlotId() ); 58 } 59 } 60 61 #endif 62 63 //-------------------------------------------------------------------- 64 65 // returns the next registered SfxControllerItem with the same id 66 67 SfxControllerItem* SfxControllerItem::GetItemLink() 68 { 69 DBG_MEMTEST(); 70 DBG_CHKTHIS(SfxControllerItem, 0); 71 return pNext == this ? 0 : pNext; 72 } 73 74 //-------------------------------------------------------------------- 75 76 // returns sal_True if this binding is really bound to a function 77 78 sal_Bool SfxControllerItem::IsBound() const 79 { 80 DBG_MEMTEST(); 81 DBG_CHKTHIS(SfxControllerItem, 0); 82 return pNext != this; 83 } 84 85 //-------------------------------------------------------------------- 86 87 // returns the associated function-id or 0 if none 88 89 // sal_uInt16 SfxControllerItem::GetId() const; 90 91 //==================================================================== 92 93 // registeres with the id at the bindings 94 95 void SfxControllerItem::Bind( sal_uInt16 nNewId, SfxBindings *pBindinx ) 96 { 97 DBG_MEMTEST(); 98 DBG_CHKTHIS(SfxControllerItem, 0); 99 DBG_ASSERT(pBindings || pBindinx, "Keine Bindings"); 100 101 if ( IsBound() ) { 102 DBG_ASSERT(pBindings, "Keine Bindings"); 103 pBindings->Release(*this); 104 } 105 106 nId = nNewId; 107 pNext = 0; 108 109 if (pBindinx) 110 pBindings = pBindinx; 111 pBindings->Register(*this); 112 } 113 114 void SfxControllerItem::BindInternal_Impl( sal_uInt16 nNewId, SfxBindings *pBindinx ) 115 { 116 DBG_MEMTEST(); 117 DBG_CHKTHIS(SfxControllerItem, 0); 118 DBG_ASSERT(pBindings || pBindinx, "Keine Bindings"); 119 120 if ( IsBound() ) { 121 DBG_ASSERT(pBindings, "Keine Bindings"); 122 pBindings->Release(*this); 123 } 124 125 nId = nNewId; 126 pNext = 0; 127 128 if (pBindinx) 129 pBindings = pBindinx; 130 pBindings->RegisterInternal_Impl(*this); 131 } 132 133 134 //==================================================================== 135 136 void SfxControllerItem::UnBind() 137 138 /* [Beschreibung] 139 140 "ost die Verbindung dieses SfxControllerItems mit der SfxBindings-Instanz, 141 an der es zur Zeit gebunden ist. Ab diesem Zeitpunkt erh"alt es keine 142 Statusbenachrichtigungen (<SfxControllerItem::StateChented()>) mehr. 143 144 145 [Querverweise] 146 147 <SfxControllerItem::ReBind()> 148 <SfxControllerItem::ClearCache()> 149 */ 150 { 151 DBG_MEMTEST(); 152 DBG_CHKTHIS(SfxControllerItem, 0); 153 DBG_ASSERT(pBindings, "Keine Bindings"); 154 DBG_ASSERT( IsBound(), "unbindings unbound SfxControllerItem" ); 155 156 pBindings->Release(*this); 157 pNext = this; 158 } 159 160 //==================================================================== 161 162 void SfxControllerItem::ReBind() 163 164 /* [Beschreibung] 165 166 Binded dieses SfxControllerItem wieder an die SfxBindings-Instanz, 167 an der es zuletzt gebunden war. Ab diesem Zeitpunkt erh"alt es wieder 168 Statusbenachrichtigungen (<SfxControllerItem::StateChented()>). 169 170 171 [Querverweise] 172 173 <SfxControllerItem::UnBind()> 174 <SfxControllerItem::ClearCache()> 175 */ 176 177 { 178 DBG_MEMTEST(); 179 DBG_CHKTHIS(SfxControllerItem, 0); 180 DBG_ASSERT(pBindings, "Keine Bindings"); 181 DBG_ASSERT( !IsBound(), "bindings rebound SfxControllerItem" ); 182 183 pBindings->Register(*this); 184 } 185 186 //==================================================================== 187 188 void SfxControllerItem::UpdateSlot() 189 190 /* [Beschreibung] 191 192 Holt den Status 'hart' neu. 193 194 [Querverweise] 195 196 <SfxControllerItem::ClearCache()> 197 */ 198 199 { 200 DBG_MEMTEST(); 201 DBG_CHKTHIS(SfxControllerItem, 0); 202 DBG_ASSERT(pBindings, "Keine Bindings"); 203 204 pBindings->Update( GetId() ); 205 } 206 207 //-------------------------------------------------------------------- 208 209 void SfxControllerItem::ClearCache() 210 211 /* [Beschreibung] 212 213 "oscht den Status-Cache f"ur dieses SfxControllerItem. D.h. beim 214 n"achsten Status-Update wird das <SfxPoolItem> auf jeden Fall geschickt, 215 auch wenn zuvor dasselbe geschickt wurde. Dies wird ben"otigt, wenn 216 ein Controller umgeschaltet werden kann und sich diesen Status 217 selbst merkt. 218 219 220 [Beispiel] 221 222 Der Kombi-Controller f"ur das Einstellen des Fl"achentyps und der 223 konkreten Auspr"agung (Farbe blau oder Schraffur X) kann im Typ 224 umgestellt werden, wird jedoch dann bei der n"achsten Selektion 225 wieder benachrichtigt, auch wenn es dieselben Daten sind. 226 227 228 [Querverweise] 229 230 <SfxControllerItem::UnBind()> 231 <SfxControllerItem::ReBind()> 232 */ 233 234 235 { 236 DBG_MEMTEST(); 237 DBG_CHKTHIS(SfxControllerItem, 0); 238 DBG_ASSERT(pBindings, "Keine Bindings"); 239 240 pBindings->ClearCache_Impl( GetId() ); 241 } 242 243 //-------------------------------------------------------------------- 244 245 // replaces the successor in the list of bindings of the same id 246 247 SfxControllerItem* SfxControllerItem::ChangeItemLink( SfxControllerItem* pNewLink ) 248 { 249 DBG_MEMTEST(); 250 DBG_CHKTHIS(SfxControllerItem, 0); 251 SfxControllerItem* pOldLink = pNext; 252 pNext = pNewLink; 253 return pOldLink == this ? 0 : pOldLink; 254 } 255 256 //-------------------------------------------------------------------- 257 258 // changes the id of unbound functions (e.g. for sub-menu-ids) 259 260 void SfxControllerItem::SetId( sal_uInt16 nItemId ) 261 { 262 DBG_MEMTEST(); 263 DBG_CHKTHIS(SfxControllerItem, 0); 264 DBG_ASSERT( !IsBound(), "changing id of bound binding" ); 265 nId = nItemId; 266 } 267 268 //-------------------------------------------------------------------- 269 270 // creates a atomic item for a controller without registration 271 272 SfxControllerItem::SfxControllerItem(): 273 nId(0), 274 pNext(this), 275 pBindings(0) 276 { 277 DBG_MEMTEST(); 278 DBG_CTOR(SfxControllerItem, 0); 279 } 280 281 //-------------------------------------------------------------------- 282 283 // creates a representation of the function nId and registeres it 284 285 SfxControllerItem::SfxControllerItem( sal_uInt16 nID, SfxBindings &rBindings ): 286 nId(nID), 287 pNext(this), 288 pBindings(&rBindings) 289 { 290 DBG_MEMTEST(); 291 DBG_CTOR(SfxControllerItem, 0); 292 Bind(nId, &rBindings); 293 } 294 295 //-------------------------------------------------------------------- 296 297 // unregisteres the item in the bindings 298 299 SfxControllerItem::~SfxControllerItem() 300 { 301 DBG_MEMTEST(); 302 if ( IsBound() ) 303 pBindings->Release(*this); 304 DBG_DTOR(SfxControllerItem, 0); 305 } 306 307 //-------------------------------------------------------------------- 308 309 void SfxControllerItem::StateChanged 310 ( 311 sal_uInt16 , // <SID> des ausl"osenden Slot 312 SfxItemState , // <SfxItemState> von 'pState' 313 const SfxPoolItem* // Slot-Status, ggf. 0 oder IsInvalidItem() 314 ) 315 316 /* [Beschreibung] 317 318 Diese virtuelle Methode wird vom SFx gerufen, um <SfxControllerItem>s 319 dar"uber zu benachrichtigen, da\s sich der Status des Slots 'nSID' 320 ge"andert hat. Der neue Wert sowie der von diesem Wert ermittelte 321 Status wird als 'pState' bzw. 'eState' mitgegeben. 322 323 Der Status eines Slots kann sich "andern, wenn z.B. das MDI-Fenster 324 gewechselt wird oder der Slot explizit mit <SfxBindings::Invalidate()> 325 invalidiert wurde. 326 327 Achtung! Die Methode wird nicht gerufen, wenn der Slot ung"ultig wurde, 328 danach jedoch wieder denselben Wert angenommen hat. 329 330 Diese Basisklasse braucht nicht gerufen zu werden, weitere Zwischenstufen 331 jedoch (z.B. <SfxToolboxControl>) sollten gerufen werden. 332 */ 333 334 { 335 DBG_MEMTEST(); 336 DBG_CHKTHIS(SfxControllerItem, 0); 337 } 338 339 //-------------------------------------------------------------------- 340 341 void SfxControllerItem::DeleteFloatingWindow() 342 { 343 DBG_MEMTEST(); 344 DBG_CHKTHIS(SfxControllerItem, 0); 345 } 346 347 //-------------------------------------------------------------------- 348 349 void SfxStatusForwarder::StateChanged 350 ( 351 sal_uInt16 nSID, // <SID> des ausl"osenden Slot 352 SfxItemState eState, // <SfxItemState> von 'pState' 353 const SfxPoolItem* pState // Slot-Status, ggf. 0 oder IsInvalidItem() 354 ) 355 356 { 357 pMaster->StateChanged( nSID, eState, pState ); 358 } 359 360 //-------------------------------------------------------------------- 361 362 SfxStatusForwarder::SfxStatusForwarder( 363 sal_uInt16 nSlotId, 364 SfxControllerItem& rMaster ): 365 SfxControllerItem( nSlotId, rMaster.GetBindings() ), 366 pMaster( &rMaster ) 367 { 368 } 369 370 //-------------------------------------------------------------------- 371 372 SfxItemState SfxControllerItem::GetItemState 373 ( 374 const SfxPoolItem* pState /* Pointer auf das <SfxPoolItem>, dessen 375 Status erfragt werden soll. */ 376 ) 377 378 /* [Beschreibung] 379 380 Statische Methode zum Ermitteln des Status des SfxPoolItem-Pointers, 381 in der Methode <SfxControllerItem::StateChanged(const SfxPoolItem*)> 382 zu verwenden. 383 384 [R"uckgabewert] 385 386 SfxItemState SFX_ITEM_UNKNOWN 387 Enabled, aber keine weitere Statusinformation 388 verf"ugbar. Typisch f"ur <Slot>s, die allenfalls 389 zeitweise disabled sind, aber ihre Darstellung sonst 390 nicht "andern. 391 392 SFX_ITEM_DISABLED 393 Disabled und keine weiter Statusinformation 394 verf"ugbar. Alle anderen ggf. angezeigten Werte sollten 395 auf den Default zur"uckgesetzt werden. 396 397 SFX_ITEM_DONTCARE 398 Enabled aber es waren nur uneindeutige Werte 399 verf"ugbar (also keine, die abgefragt werden k"onnen). 400 401 SFX_ITEM_AVAILABLE 402 Enabled und mit verf"ugbarem Wert, der von 'pState' 403 erfragbar ist. Der Typ ist dabei im gesamten 404 Programm eindeutig und durch den Slot festgelegt. 405 */ 406 407 { 408 return !pState 409 ? SFX_ITEM_DISABLED 410 : IsInvalidItem(pState) 411 ? SFX_ITEM_DONTCARE 412 : pState->ISA(SfxVoidItem) && !pState->Which() 413 ? SFX_ITEM_UNKNOWN 414 : SFX_ITEM_AVAILABLE; 415 } 416 417 //-------------------------------------------------------------------- 418 419 SfxMapUnit SfxControllerItem::GetCoreMetric() const 420 421 /* [Beschreibung] 422 423 Holt vom zust"andigen Pool die Ma\seinheit ab, in der das Status-Item 424 vorliegt. 425 */ 426 427 { 428 SfxStateCache *pCache = pBindings->GetStateCache( nId ); 429 SfxDispatcher *pDispat = pBindings->GetDispatcher_Impl(); 430 431 if ( !pDispat ) 432 { 433 SfxViewFrame* pViewFrame = SfxViewFrame::Current(); 434 if ( !pViewFrame ) 435 SfxViewFrame::GetFirst(); 436 if ( pViewFrame ) 437 pDispat = pViewFrame->GetDispatcher(); 438 } 439 440 if ( pDispat && pCache ) 441 { 442 const SfxSlotServer *pServer = pCache->GetSlotServer( *pDispat ); 443 if ( pServer ) 444 { 445 SfxShell *pSh = pDispat->GetShell( pServer->GetShellLevel() ); 446 SfxItemPool &rPool = pSh->GetPool(); 447 sal_uInt16 nWhich = rPool.GetWhich( nId ); 448 return rPool.GetMetric( nWhich ); 449 } 450 } 451 452 DBG_WARNING( "W1: Can not find ItemPool!" ); 453 return SFX_MAPUNIT_100TH_MM; 454 } 455 456 //------------------------------------------------------------------------ 457 458 #ifdef _MSC_VER 459 #pragma optimize("g",off) 460 #endif 461 462 463