LibreOffice Module sfx2 (master) 1
bindings.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <iomanip>
23
25#include <osl/diagnose.h>
26#include <sal/log.hxx>
27#include <svl/itempool.hxx>
28#include <svl/itemiter.hxx>
29#include <svl/eitem.hxx>
30#include <svl/intitem.hxx>
31#include <svl/stritem.hxx>
32#include <vcl/svapp.hxx>
33#include <vcl/timer.hxx>
34#include <com/sun/star/frame/XDispatch.hpp>
35#include <com/sun/star/frame/XDispatchProvider.hpp>
36#include <com/sun/star/frame/DispatchResultState.hpp>
37#include <itemdel.hxx>
38
39//Includes below due to nInReschedule
40#include <sfx2/bindings.hxx>
41#include <sfx2/msg.hxx>
42#include <statcach.hxx>
43#include <sfx2/ctrlitem.hxx>
44#include <sfx2/app.hxx>
45#include <sfx2/dispatch.hxx>
46#include <sfx2/module.hxx>
47#include <sfx2/request.hxx>
48#include <workwin.hxx>
49#include <unoctitm.hxx>
50#include <sfx2/viewfrm.hxx>
51#include <sfx2/objsh.hxx>
52#include <sfx2/msgpool.hxx>
53
54#include <cstddef>
55#include <memory>
56#include <unordered_map>
57#include <utility>
58#include <vector>
59
60using namespace ::com::sun::star;
61using namespace ::com::sun::star::uno;
62using namespace ::com::sun::star::util;
63
64#define TIMEOUT_FIRST 300
65#define TIMEOUT_UPDATING 20
66
68{
69 sal_uInt16 nWhichId; // If available: Which-Id, else: nSlotId
70 const SfxSlot* pSlot; // Pointer to <Master-Slot>
71 SfxStateCache& rCache; // Pointer to StatusCache
72
73 SfxFoundCache_Impl(sal_uInt16 nW, const SfxSlot *pS, SfxStateCache& rC)
74 : nWhichId(nW)
75 , pSlot(pS)
76 , rCache(rC)
77 {}
78};
79
81{
82 std::vector<SfxFoundCache_Impl> maData;
83
84public:
85
87 {
88 return maData[i];
89 }
90
91 size_t size() const
92 {
93 return maData.size();
94 }
95
97 {
98 maData.push_back(p);
99 }
100};
101
103{
104public:
105 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
106 css::uno::Reference< css::frame::XDispatchProvider > xProv;
107 std::unique_ptr<SfxWorkWindow> mxWorkWin;
109 std::vector<std::unique_ptr<SfxStateCache>> pCaches; // One cache for each binding
110 std::size_t nCachedFunc1; // index for the last one called
111 std::size_t nCachedFunc2; // index for the second last called
112 std::size_t nMsgPos; // Message-Position relative the one to be updated
114 bool bMsgDirty; // Has a MessageServer been invalidated?
115 bool bAllMsgDirty; // Has a MessageServer been invalidated?
116 bool bAllDirty; // After InvalidateAll
117 bool bCtrlReleased; // while EnterRegistrations
118 AutoTimer aAutoTimer { "sfx::SfxBindings aAutoTimer" }; // for volatile Slots
119 bool bInUpdate; // for Assertions
120 bool bInNextJob; // for Assertions
121 bool bFirstRound; // First round in Update
122 sal_uInt16 nOwnRegLevel; // Counts the real Locks, except those of the Super Bindings
123 std::unordered_map< sal_uInt16, bool >
124 m_aInvalidateSlots; // store slots which are invalidated while in update
125};
126
128: pImpl(new SfxBindings_Impl),
129 pDispatcher(nullptr),
130 nRegLevel(1) // first becomes 0, when the Dispatcher is set
131
132{
133 pImpl->nMsgPos = 0;
134 pImpl->bAllMsgDirty = true;
135 pImpl->bContextChanged = false;
136 pImpl->bMsgDirty = true;
137 pImpl->bAllDirty = true;
138 pImpl->nCachedFunc1 = 0;
139 pImpl->nCachedFunc2 = 0;
140 pImpl->bCtrlReleased = false;
141 pImpl->bFirstRound = false;
142 pImpl->bInNextJob = false;
143 pImpl->bInUpdate = false;
144 pImpl->pSubBindings = nullptr;
145 pImpl->nOwnRegLevel = nRegLevel;
146
147 // all caches are valid (no pending invalidate-job)
148 // create the list of caches
149 pImpl->aAutoTimer.SetInvokeHandler( LINK(this, SfxBindings, NextJob) );
150}
151
152
154
155/* [Description]
156
157 Destructor of the SfxBindings class. The one, for each <SfxApplication>
158 existing Instance is automatically destroyed by the <SfxApplication>
159 after the execution of <SfxApplication::Exit()>.
160
161 The still existing <SfxControllerItem> instances, which are registered
162 by the SfxBindings instance, are automatically destroyed in the Destructor.
163 These are usually the Floating-Toolboxen, Value-Sets
164 etc. Arrays of SfxControllerItems may at this time no longer exist.
165*/
166
167{
168 // The SubBindings should not be locked!
169 pImpl->pSubBindings = nullptr;
170
172
173 pImpl->aAutoTimer.Stop();
175
176 // Delete Caches
177 pImpl->pCaches.clear();
178
179 pImpl->mxWorkWin.reset();
180}
181
182
184{
185 // in the first round delete Controllers
186 std::size_t nCount = pImpl->pCaches.size();
187 std::size_t nCache;
188 for ( nCache = 0; nCache < nCount; ++nCache )
189 {
190 // Remember were you are
191 SfxStateCache *pCache = pImpl->pCaches[nCache].get();
192 sal_uInt16 nSlotId = pCache->GetId();
193
194 // Re-align, because the cache may have been reduced
195 std::size_t nNewCount = pImpl->pCaches.size();
196 if ( nNewCount < nCount )
197 {
198 nCache = GetSlotPos(nSlotId);
199 if ( nCache >= nNewCount ||
200 nSlotId != pImpl->pCaches[nCache]->GetId() )
201 --nCache;
202 nCount = nNewCount;
203 }
204 }
205
206 // Delete all Caches
207 for ( nCache = pImpl->pCaches.size(); nCache > 0; --nCache )
208 {
209 // Get Cache via css::sdbcx::Index
210 SfxStateCache *pCache = pImpl->pCaches[ nCache-1 ].get();
211
212 // unbind all controllers in the cache
213 SfxControllerItem *pNext;
214 for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
215 pCtrl; pCtrl = pNext )
216 {
217 pNext = pCtrl->GetItemLink();
218 pCtrl->UnBind();
219 }
220
221 if ( pCache->GetInternalController() )
222 pCache->GetInternalController()->UnBind();
223
224 // Delete Cache
225 pImpl->pCaches.erase(pImpl->pCaches.begin() + nCache - 1);
226 }
227}
228
229
230void SfxBindings::HidePopups( bool bHide )
231{
232 // Hide SfxChildWindows
233 DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
234 if ( pImpl->mxWorkWin )
235 pImpl->mxWorkWin->HidePopups_Impl( bHide );
236}
237
238void SfxBindings::Update_Impl(SfxStateCache& rCache /*The up to date SfxStatusCache*/)
239{
240 if (rCache.GetDispatch().is() && rCache.GetItemLink())
241 {
242 rCache.SetCachedState(true);
243 if (!rCache.GetInternalController())
244 return;
245 }
246
247 if ( !pDispatcher )
248 return;
249
250 // gather together all with the same status method which are dirty
251 SfxDispatcher &rDispat = *pDispatcher;
252 const SfxSlot *pRealSlot = nullptr;
253 const SfxSlotServer* pMsgServer = nullptr;
255 std::optional<SfxItemSet> pSet = CreateSet_Impl(rCache, pRealSlot, &pMsgServer, aFound);
256 bool bUpdated = false;
257 if ( pSet )
258 {
259 // Query Status
260 if ( rDispat.FillState_( *pMsgServer, *pSet, pRealSlot ) )
261 {
262 // Post Status
263 for ( size_t nPos = 0; nPos < aFound.size(); ++nPos )
264 {
265 const SfxFoundCache_Impl& rFound = aFound[nPos];
266 sal_uInt16 nWhich = rFound.nWhichId;
267 const SfxPoolItem *pItem = nullptr;
268 SfxItemState eState = pSet->GetItemState(nWhich, true, &pItem);
269 if ( eState == SfxItemState::DEFAULT && SfxItemPool::IsWhich(nWhich) )
270 pItem = &pSet->Get(nWhich);
271 UpdateControllers_Impl( rFound, pItem, eState );
272 }
273 bUpdated = true;
274 }
275
276 pSet.reset();
277 }
278
279 if (!bUpdated)
280 {
281 SfxFoundCache_Impl aFoundCache(0, pRealSlot, rCache);
282 UpdateControllers_Impl( aFoundCache, nullptr, SfxItemState::DISABLED);
283 }
284}
285
287{
288 for (auto const& slot : pImpl->m_aInvalidateSlots)
289 Invalidate( slot.first );
290
291 pImpl->m_aInvalidateSlots.clear();
292}
293
294
296{
297 pImpl->m_aInvalidateSlots[nId] = true;
298}
299
300
302(
303 sal_uInt16 nId // the bound and up-to-date Slot-Id
304)
305{
306 if ( pDispatcher )
308
309 if ( pImpl->pSubBindings )
310 pImpl->pSubBindings->Update( nId );
311
312 SfxStateCache* pCache = GetStateCache( nId );
313 if ( !pCache )
314 return;
315
316 pImpl->bInUpdate = true;
317 if ( pImpl->bMsgDirty )
318 {
320 pCache = GetStateCache( nId );
321 }
322
323 if (pCache)
324 {
325 bool bInternalUpdate = true;
326 if( pCache->GetDispatch().is() && pCache->GetItemLink() )
327 {
328 pCache->SetCachedState(true);
329 bInternalUpdate = ( pCache->GetInternalController() != nullptr );
330 }
331
332 if ( bInternalUpdate )
333 {
334 // Query Status
335 const SfxSlotServer* pMsgServer = pDispatcher ? pCache->GetSlotServer(*pDispatcher, pImpl->xProv) : nullptr;
336 if ( !pCache->IsControllerDirty() )
337 {
338 pImpl->bInUpdate = false;
340 return;
341 }
342 if (!pMsgServer)
343 {
344 pCache->SetState(SfxItemState::DISABLED, nullptr);
345 pImpl->bInUpdate = false;
347 return;
348 }
349
350 Update_Impl(*pCache);
351 }
352
353 pImpl->bAllDirty = false;
354 }
355
356 pImpl->bInUpdate = false;
358}
359
360
362{
363 if ( pImpl->pSubBindings )
364 pImpl->pSubBindings->Update();
365
366 if ( !pDispatcher )
367 return;
368
369 if ( nRegLevel )
370 return;
371
372 pImpl->bInUpdate = true;
375 while ( !NextJob_Impl(nullptr) )
376 ; // loop
377 pImpl->bInUpdate = false;
379}
380
381
383(
384 const SfxItemSet& rSet // status values to be set
385)
386{
387 // when locked then only invalidate
388 if ( nRegLevel )
389 {
390 SfxItemIter aIter(rSet);
391 for ( const SfxPoolItem *pItem = aIter.GetCurItem();
392 pItem;
393 pItem = aIter.NextItem() )
394 Invalidate( pItem->Which() );
395 }
396 else
397 {
398 // Status may be accepted only if all slot-pointers are set
399 if ( pImpl->bMsgDirty )
401
402 // Iterate over the itemset, update if the slot bound
404 SfxItemIter aIter(rSet);
405 for ( const SfxPoolItem *pItem = aIter.GetCurItem();
406 pItem;
407 pItem = aIter.NextItem() )
408 {
409 SfxStateCache* pCache =
410 GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
411 if ( pCache )
412 {
413 // Update status
414 if ( !pCache->IsControllerDirty() )
415 pCache->Invalidate(false);
416 pCache->SetState( SfxItemState::DEFAULT, pItem );
417
419 }
420 }
421 }
422}
423
424
426(
427 const SfxPoolItem& rItem // Status value to be set
428)
429{
430 if ( nRegLevel )
431 {
432 Invalidate( rItem.Which() );
433 }
434 else
435 {
436 // Status may be accepted only if all slot-pointers are set
437 if ( pImpl->bMsgDirty )
439
440 //update if the slot bound
442 "cannot set items with which-id" );
443 SfxStateCache* pCache = GetStateCache( rItem.Which() );
444 if ( pCache )
445 {
446 // Update Status
447 if ( !pCache->IsControllerDirty() )
448 pCache->Invalidate(false);
449 pCache->SetState( SfxItemState::DEFAULT, &rItem );
450
452 }
453 }
454}
455
456
458{
459 SfxStateCache* pCache = GetStateCache( nId );
460 if ( !pCache && pImpl->pSubBindings )
461 return pImpl->pSubBindings->GetAnyStateCache_Impl( nId );
462 return pCache;
463}
464
466(
467 sal_uInt16 nId /* Slot-Id, which SfxStatusCache is to be found */
468)
469{
470 return GetStateCache(nId, nullptr);
471}
472
474(
475 sal_uInt16 nId, /* Slot-Id, which SfxStatusCache is to be found */
476 std::size_t * pPos /* NULL for instance the position from which the
477 bindings are to be searched binary. Returns the
478 position back for where the nId was found,
479 or where it was inserted. */
480)
481{
482 // is the specified function bound?
483 const std::size_t nStart = ( pPos ? *pPos : 0 );
484 const std::size_t nPos = GetSlotPos( nId, nStart );
485
486 if ( nPos < pImpl->pCaches.size() &&
487 pImpl->pCaches[nPos]->GetId() == nId )
488 {
489 if ( pPos )
490 *pPos = nPos;
491 return pImpl->pCaches[nPos].get();
492 }
493 return nullptr;
494}
495
496
498(
499 bool bWithMsg /* true Mark Slot Server as invalid
500 false Slot Server remains valid */
501)
502{
503 DBG_ASSERT( !pImpl->bInUpdate, "SfxBindings::Invalidate while in update" );
504
505 if ( pImpl->pSubBindings )
506 pImpl->pSubBindings->InvalidateAll( bWithMsg );
507
508 // everything is already set dirty or downing => nothing to do
509 if ( !pDispatcher ||
510 ( pImpl->bAllDirty && ( !bWithMsg || pImpl->bAllMsgDirty ) ) ||
511 SfxGetpApp()->IsDowning() )
512 {
513 return;
514 }
515
516 pImpl->bAllMsgDirty = pImpl->bAllMsgDirty || bWithMsg;
517 pImpl->bMsgDirty = pImpl->bMsgDirty || pImpl->bAllMsgDirty || bWithMsg;
518 pImpl->bAllDirty = true;
519
520 for (std::unique_ptr<SfxStateCache>& pCache : pImpl->pCaches)
521 pCache->Invalidate(bWithMsg);
522
523 pImpl->nMsgPos = 0;
524 if ( !nRegLevel )
525 {
526 pImpl->aAutoTimer.Stop();
527 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
528 pImpl->aAutoTimer.Start();
529 }
530}
531
532
534(
535 const sal_uInt16* pIds /* numerically sorted NULL-terminated array of
536 slot IDs (individual, not as a couple!) */
537)
538{
539 if ( pImpl->bInUpdate )
540 {
541 sal_Int32 i = 0;
542 while ( pIds[i] != 0 )
544
545 if ( pImpl->pSubBindings )
546 pImpl->pSubBindings->Invalidate( pIds );
547 return;
548 }
549
550 if ( pImpl->pSubBindings )
551 pImpl->pSubBindings->Invalidate( pIds );
552
553 // everything is already set dirty or downing => nothing to do
554 if ( !pDispatcher || pImpl->bAllDirty || SfxGetpApp()->IsDowning() )
555 return;
556
557 // Search binary in always smaller areas
558 for ( std::size_t n = GetSlotPos(*pIds);
559 *pIds && n < pImpl->pCaches.size();
560 n = GetSlotPos(*pIds, n) )
561 {
562 // If SID is ever bound, then invalidate the cache
563 SfxStateCache *pCache = pImpl->pCaches[n].get();
564 if ( pCache->GetId() == *pIds )
565 pCache->Invalidate(false);
566
567 // Next SID
568 if ( !*++pIds )
569 break;
570 assert( *pIds > *(pIds-1) );
571 }
572
573 // if not enticed to start update timer
574 pImpl->nMsgPos = 0;
575 if ( !nRegLevel )
576 {
577 pImpl->aAutoTimer.Stop();
578 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
579 pImpl->aAutoTimer.Start();
580 }
581}
582
583
585(
586 const SfxShell& rSh, /* <SfxShell> whose Slot-Ids should be
587 invalidated */
588 bool bDeep /* true
589 also the SfxShell's inherited slot IDs are invalidated
590
591 false
592 the inherited and not overridden Slot-Ids are
593 invalidated */
594 // for now always bDeep
595)
596{
597 DBG_ASSERT( !pImpl->bInUpdate, "SfxBindings::Invalidate while in update" );
598
599 if ( pImpl->pSubBindings )
600 pImpl->pSubBindings->InvalidateShell( rSh, bDeep );
601
602 if ( !pDispatcher || pImpl->bAllDirty || SfxGetpApp()->IsDowning() )
603 return;
604
605 // flush now already, it is done in GetShellLevel (rsh) anyway,
606 // important so that is set correctly: pImpl-> ball(Msg)Dirty
608
609 if ((pImpl->bAllDirty && pImpl->bAllMsgDirty) || SfxGetpApp()->IsDowning())
610 {
611 // if the next one is anyway, then all the servers are collected
612 return;
613 }
614
615 // Find Level
616 sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
617 if ( nLevel == USHRT_MAX )
618 return;
619
620 for (std::unique_ptr<SfxStateCache>& pCache : pImpl->pCaches)
621 {
622 const SfxSlotServer *pMsgServer =
623 pCache->GetSlotServer(*pDispatcher, pImpl->xProv);
624 if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
625 pCache->Invalidate(false);
626 }
627 pImpl->nMsgPos = 0;
628 if ( !nRegLevel )
629 {
630 pImpl->aAutoTimer.Stop();
631 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
632 pImpl->aAutoTimer.Start();
633 pImpl->bFirstRound = true;
634 }
635}
636
637
639(
640 sal_uInt16 nId // Status value to be set
641)
642{
643 if ( pImpl->bInUpdate )
644 {
646 if ( pImpl->pSubBindings )
647 pImpl->pSubBindings->Invalidate( nId );
648 return;
649 }
650
651 if ( pImpl->pSubBindings )
652 pImpl->pSubBindings->Invalidate( nId );
653
654 if ( !pDispatcher || pImpl->bAllDirty || SfxGetpApp()->IsDowning() )
655 return;
656
658 if ( pCache )
659 {
660 pCache->Invalidate(false);
661 pImpl->nMsgPos = std::min(GetSlotPos(nId), pImpl->nMsgPos);
662 if ( !nRegLevel )
663 {
664 pImpl->aAutoTimer.Stop();
665 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
666 pImpl->aAutoTimer.Start();
667 }
668 }
669}
670
671
673(
674 sal_uInt16 nId, // Status value to be set
675 bool bWithItem, // Clear StateCache?
676 bool bWithMsg // Get new SlotServer?
677)
678{
679 DBG_ASSERT( !pImpl->bInUpdate, "SfxBindings::Invalidate while in update" );
680
681 if ( pImpl->pSubBindings )
682 pImpl->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
683
684 if ( SfxGetpApp()->IsDowning() )
685 return;
686
688 if ( !pCache )
689 return;
690
691 if ( bWithItem )
692 pCache->ClearCache();
693 pCache->Invalidate(bWithMsg);
694
695 if ( !pDispatcher || pImpl->bAllDirty )
696 return;
697
698 pImpl->nMsgPos = std::min(GetSlotPos(nId), pImpl->nMsgPos);
699 if ( !nRegLevel )
700 {
701 pImpl->aAutoTimer.Stop();
702 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
703 pImpl->aAutoTimer.Start();
704 }
705}
706
707
708std::size_t SfxBindings::GetSlotPos( sal_uInt16 nId, std::size_t nStartSearchAt )
709{
710 // answer immediately if a function-seek comes repeated
711 if ( pImpl->nCachedFunc1 < pImpl->pCaches.size() &&
712 pImpl->pCaches[pImpl->nCachedFunc1]->GetId() == nId )
713 {
714 return pImpl->nCachedFunc1;
715 }
716 if ( pImpl->nCachedFunc2 < pImpl->pCaches.size() &&
717 pImpl->pCaches[pImpl->nCachedFunc2]->GetId() == nId )
718 {
719 // swap the caches
720 std::swap(pImpl->nCachedFunc1, pImpl->nCachedFunc2);
721 return pImpl->nCachedFunc1;
722 }
723
724 // binary search, if not found, seek to target-position
725 if ( pImpl->pCaches.size() <= nStartSearchAt )
726 {
727 return 0;
728 }
729 if ( pImpl->pCaches.size() == (nStartSearchAt+1) )
730 {
731 return pImpl->pCaches[nStartSearchAt]->GetId() >= nId ? 0 : 1;
732 }
733 std::size_t nLow = nStartSearchAt;
734 std::size_t nMid = 0;
735 std::size_t nHigh = 0;
736 bool bFound = false;
737 nHigh = pImpl->pCaches.size() - 1;
738 while ( !bFound && nLow <= nHigh )
739 {
740 nMid = (nLow + nHigh) >> 1;
741 DBG_ASSERT( nMid < pImpl->pCaches.size(), "bsearch is buggy" );
742 int nDiff = static_cast<int>(nId) - static_cast<int>( (pImpl->pCaches[nMid])->GetId() );
743 if ( nDiff < 0)
744 { if ( nMid == 0 )
745 break;
746 nHigh = nMid - 1;
747 }
748 else if ( nDiff > 0 )
749 { nLow = nMid + 1;
750 if ( nLow == 0 )
751 break;
752 }
753 else
754 bFound = true;
755 }
756 std::size_t nPos = bFound ? nMid : nLow;
757 DBG_ASSERT( nPos <= pImpl->pCaches.size(), "" );
758 DBG_ASSERT( nPos == pImpl->pCaches.size() ||
759 nId <= pImpl->pCaches[nPos]->GetId(), "" );
760 DBG_ASSERT( nPos == nStartSearchAt ||
761 nId > pImpl->pCaches[nPos-1]->GetId(), "" );
762 DBG_ASSERT( ( (nPos+1) >= pImpl->pCaches.size() ) ||
763 nId < pImpl->pCaches[nPos+1]->GetId(), "" );
764 pImpl->nCachedFunc2 = pImpl->nCachedFunc1;
765 pImpl->nCachedFunc1 = nPos;
766 return nPos;
767}
768
770{
771 Register_Impl( rItem, true );
772
773}
774
776{
777 Register_Impl( rItem, false );
778}
779
780void SfxBindings::Register_Impl( SfxControllerItem& rItem, bool bInternal )
781{
782// DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
783 DBG_ASSERT( !pImpl->bInNextJob, "SfxBindings::Register while status-updating" );
784
785 // insert new cache if it does not already exist
786 sal_uInt16 nId = rItem.GetId();
787 std::size_t nPos = GetSlotPos(nId);
788 if ( nPos >= pImpl->pCaches.size() ||
789 pImpl->pCaches[nPos]->GetId() != nId )
790 {
791 pImpl->pCaches.insert( pImpl->pCaches.begin() + nPos, std::make_unique<SfxStateCache>(nId) );
792 DBG_ASSERT( nPos == 0 ||
793 pImpl->pCaches[nPos]->GetId() >
794 pImpl->pCaches[nPos-1]->GetId(), "" );
795 DBG_ASSERT( (nPos == pImpl->pCaches.size()-1) ||
796 pImpl->pCaches[nPos]->GetId() <
797 pImpl->pCaches[nPos+1]->GetId(), "" );
798 pImpl->bMsgDirty = true;
799 }
800
801 // enqueue the new binding
802 if ( bInternal )
803 {
804 pImpl->pCaches[nPos]->SetInternalController( &rItem );
805 }
806 else
807 {
808 SfxControllerItem *pOldItem = pImpl->pCaches[nPos]->ChangeItemLink(&rItem);
809 rItem.ChangeItemLink(pOldItem);
810 }
811}
812
813
815{
816 DBG_ASSERT( !pImpl->bInNextJob, "SfxBindings::Release while status-updating" );
818
819 // find the bound function
820 sal_uInt16 nId = rItem.GetId();
821 std::size_t nPos = GetSlotPos(nId);
822 SfxStateCache* pCache = (nPos < pImpl->pCaches.size()) ? pImpl->pCaches[nPos].get() : nullptr;
823 if ( pCache && pCache->GetId() == nId )
824 {
825 if ( pCache->GetInternalController() == &rItem )
826 {
828 }
829 else
830 {
831 // is this the first binding in the list?
832 SfxControllerItem* pItem = pCache->GetItemLink();
833 if ( pItem == &rItem )
834 pCache->ChangeItemLink( rItem.GetItemLink() );
835 else
836 {
837 // search the binding in the list
838 while ( pItem && pItem->GetItemLink() != &rItem )
839 pItem = pItem->GetItemLink();
840
841 // unlink it if it was found
842 if ( pItem )
843 pItem->ChangeItemLink( rItem.GetItemLink() );
844 }
845 }
846
847 // was this the last controller?
848 if ( pCache->GetItemLink() == nullptr && !pCache->GetInternalController() )
849 {
850 pImpl->bCtrlReleased = true;
851 }
852 }
853
855}
856
857
858const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems )
859{
860 if( !nId || !pDispatcher )
861 return nullptr;
862
863 return Execute_Impl( nId, ppItems, 0, SfxCallMode::SYNCHRON, nullptr );
864}
865
866bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, SfxCallMode nCallMode )
867{
868 if( !nId || !pDispatcher )
869 return false;
870
871 const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, 0, nCallMode, nullptr );
872 return ( pRet != nullptr );
873}
874
875const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
876 const SfxPoolItem **ppInternalArgs, bool bGlobalOnly )
877{
878 SfxStateCache *pCache = GetStateCache( nId );
879 if ( !pCache )
880 {
881 SfxBindings *pBind = pImpl->pSubBindings;
882 while ( pBind )
883 {
884 if ( pBind->GetStateCache( nId ) )
885 return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
886 pBind = pBind->pImpl->pSubBindings;
887 }
888 }
889
890 SfxDispatcher &rDispatcher = *pDispatcher;
891 rDispatcher.Flush();
892
893 // get SlotServer (Slot+ShellLevel) and Shell from cache
894 std::unique_ptr<SfxStateCache> xCache;
895 if ( !pCache )
896 {
897 // Execution of non cached slots (Accelerators don't use Controllers)
898 // slot is uncached, use SlotCache to handle external dispatch providers
899 xCache.reset(new SfxStateCache(nId));
900 pCache = xCache.get();
901 }
902
903 pCache->GetSlotServer( rDispatcher, pImpl->xProv ); // make pCache->GetDispatch() up to date
904 if ( pCache->GetDispatch().is() )
905 {
906 DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" );
907
909 SfxRequest aReq( nId, nCallMode, rPool );
910 aReq.SetModifier( nModi );
911 if( ppItems )
912 while( *ppItems )
913 aReq.AppendItem( **ppItems++ );
914
915 // cache binds to an external dispatch provider
916 sal_Int16 eRet = pCache->Dispatch( aReq.GetArgs(), nCallMode == SfxCallMode::SYNCHRON );
917 std::unique_ptr<SfxPoolItem> pPool;
918 if ( eRet == css::frame::DispatchResultState::DONTKNOW )
919 pPool.reset( new SfxVoidItem( nId ) );
920 else
921 pPool.reset( new SfxBoolItem( nId, eRet == css::frame::DispatchResultState::SUCCESS) );
922
923 auto pTemp = pPool.get();
924 DeleteItemOnIdle( std::move(pPool) );
925 return pTemp;
926 }
927
928 // slot is handled internally by SfxDispatcher
929 if ( pImpl->bMsgDirty )
931
932 SfxShell *pShell=nullptr;
933 const SfxSlot *pSlot=nullptr;
934
935 const SfxSlotServer* pServer = pCache->GetSlotServer( rDispatcher, pImpl->xProv );
936 if ( !pServer )
937 {
938 return nullptr;
939 }
940 else
941 {
942 pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
943 pSlot = pServer->GetSlot();
944 }
945
946 if ( bGlobalOnly )
947 if ( dynamic_cast< const SfxModule *>( pShell ) == nullptr && dynamic_cast< const SfxApplication *>( pShell ) == nullptr && dynamic_cast< const SfxViewFrame *>( pShell ) == nullptr )
948 return nullptr;
949
950 SfxItemPool &rPool = pShell->GetPool();
951 SfxRequest aReq( nId, nCallMode, rPool );
952 aReq.SetModifier( nModi );
953 if( ppItems )
954 while( *ppItems )
955 aReq.AppendItem( **ppItems++ );
956 if ( ppInternalArgs )
957 {
958 SfxAllItemSet aSet( rPool );
959 for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
960 aSet.Put( **pArg );
961 aReq.SetInternalArgs_Impl( aSet );
962 }
963
964 Execute_Impl( aReq, pSlot, pShell );
965
966 const SfxPoolItem* pRet = aReq.GetReturnValue();
967 if ( !pRet )
968 {
969 std::unique_ptr<SfxPoolItem> pVoid(new SfxVoidItem( nId ));
970 pRet = pVoid.get();
971 DeleteItemOnIdle( std::move(pVoid) );
972 }
973
974 return pRet;
975}
976
977void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
978{
979 SfxItemPool &rPool = pShell->GetPool();
980
981 if ( SfxSlotKind::Attribute == pSlot->GetKind() )
982 {
983 // Which value has to be mapped for Attribute slots
984 const sal_uInt16 nSlotId = pSlot->GetSlotId();
985 aReq.SetSlot( nSlotId );
986 if ( pSlot->IsMode(SfxSlotMode::TOGGLE) )
987 {
988 // The value is attached to a toggleable attribute (Bools)
989 sal_uInt16 nWhich = pSlot->GetWhich(rPool);
990 SfxItemSet aSet(rPool, nWhich, nWhich);
991 SfxStateFunc pFunc = pSlot->GetStateFnc();
992 (*pFunc)(pShell, aSet);
993 const SfxPoolItem *pOldItem;
994 SfxItemState eState = aSet.GetItemState(nWhich, true, &pOldItem);
995 if ( eState == SfxItemState::DISABLED )
996 return;
997
998 if ( SfxItemState::DEFAULT == eState && SfxItemPool::IsWhich(nWhich) )
999 pOldItem = &aSet.Get(nWhich);
1000
1001 if ( SfxItemState::SET == eState ||
1002 ( SfxItemState::DEFAULT == eState &&
1003 SfxItemPool::IsWhich(nWhich) &&
1004 pOldItem ) )
1005 {
1006 if ( auto pOldBoolItem = dynamic_cast< const SfxBoolItem *>( pOldItem ) )
1007 {
1008 // we can toggle Bools
1009 bool bOldValue = pOldBoolItem->GetValue();
1010 std::unique_ptr<SfxBoolItem> pNewItem(static_cast<SfxBoolItem*>(pOldItem->Clone()));
1011 pNewItem->SetValue( !bOldValue );
1012 aReq.AppendItem( *pNewItem );
1013 }
1014 else if ( auto pOldEnumItem = dynamic_cast< const SfxEnumItemInterface *>( pOldItem ) )
1015 {
1016 if (pOldEnumItem->HasBoolValue())
1017 {
1018 // and Enums with Bool-Interface
1019 std::unique_ptr<SfxEnumItemInterface> pNewItem(
1020 static_cast<SfxEnumItemInterface*>(pOldEnumItem->Clone()));
1021 pNewItem->SetBoolValue(!pOldEnumItem->GetBoolValue());
1022 aReq.AppendItem( *pNewItem );
1023 }
1024 }
1025 else {
1026 OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1027 }
1028 }
1029 else if ( SfxItemState::DONTCARE == eState )
1030 {
1031 // Create one Status-Item for each Factory
1032 std::unique_ptr<SfxPoolItem> pNewItem = pSlot->GetType()->CreateItem();
1033 DBG_ASSERT( pNewItem, "Toggle to slot without ItemFactory" );
1034 pNewItem->SetWhich( nWhich );
1035
1036 if ( auto pNewBoolItem = dynamic_cast<SfxBoolItem *>( pNewItem.get() ) )
1037 {
1038 // we can toggle Bools
1039 pNewBoolItem->SetValue( true );
1040 aReq.AppendItem( *pNewItem );
1041 }
1042 else if ( auto pEnumItem = dynamic_cast<SfxEnumItemInterface *>( pNewItem.get() ) )
1043 {
1044 if (pEnumItem->HasBoolValue())
1045 {
1046 // and Enums with Bool-Interface
1047 pEnumItem->SetBoolValue(true);
1048 aReq.AppendItem( *pNewItem );
1049 }
1050 }
1051 else {
1052 OSL_FAIL( "Toggle only for Enums and Bools allowed" );
1053 }
1054 }
1055 else {
1056 OSL_FAIL( "suspicious Toggle-Slot" );
1057 }
1058 }
1059
1060 pDispatcher->Execute_( *pShell, *pSlot, aReq, aReq.GetCallMode() | SfxCallMode::RECORD );
1061 }
1062 else
1063 pDispatcher->Execute_( *pShell, *pSlot, aReq, aReq.GetCallMode() | SfxCallMode::RECORD );
1064}
1065
1066
1068{
1069 // synchronize
1070 pDispatcher->Flush();
1071
1072 if ( pImpl->bAllMsgDirty )
1073 {
1074 if ( !nRegLevel )
1075 {
1076 pImpl->bContextChanged = false;
1077 }
1078 else
1079 pImpl->bContextChanged = true;
1080 }
1081
1082 for (size_t i = 0; i < pImpl->pCaches.size(); ++i)
1083 {
1084 //GetSlotServer can modify pImpl->pCaches
1085 pImpl->pCaches[i]->GetSlotServer(*pDispatcher, pImpl->xProv);
1086 }
1087 pImpl->bMsgDirty = pImpl->bAllMsgDirty = false;
1088
1089 Broadcast( SfxHint(SfxHintId::DocChanged) );
1090}
1091
1092
1093std::optional<SfxItemSet> SfxBindings::CreateSet_Impl
1094(
1095 SfxStateCache& rCache, // in: Status-Cache from nId
1096 const SfxSlot*& pRealSlot, // out: RealSlot to nId
1097 const SfxSlotServer** pMsgServer, // out: Slot-Server to nId
1098 SfxFoundCacheArr_Impl& rFound // out: List of Caches for Siblings
1099)
1100{
1101 DBG_ASSERT( !pImpl->bMsgDirty, "CreateSet_Impl with dirty MessageServer" );
1102 assert(pDispatcher);
1103
1104 const SfxSlotServer* pMsgSvr = rCache.GetSlotServer(*pDispatcher, pImpl->xProv);
1105 if (!pMsgSvr)
1106 return {};
1107
1108 pRealSlot = nullptr;
1109 *pMsgServer = pMsgSvr;
1110
1111 sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
1112 SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
1113 if ( !pShell ) // rare GPF when browsing through update from Inet-Notify
1114 return {};
1115
1116 SfxItemPool &rPool = pShell->GetPool();
1117
1118 // get the status method, which is served by the rCache
1119 SfxStateFunc pFnc = nullptr;
1120 pRealSlot = pMsgSvr->GetSlot();
1121
1122 pFnc = pRealSlot->GetStateFnc();
1123
1124 // the RealSlot is always on
1125 SfxFoundCache_Impl aFound(pRealSlot->GetWhich(rPool), pRealSlot, rCache);
1126 rFound.push_back( aFound );
1127
1128 // Search through the bindings for slots served by the same function. This , // will only affect slots which are present in the found interface.
1129
1130 // The position of the Statecaches in StateCache-Array
1131 std::size_t nCachePos = pImpl->nMsgPos;
1132 const SfxSlot *pSibling = pRealSlot->GetNextSlot();
1133
1134 // the Slots ODF and interfaces are linked in a circle
1135 while ( pSibling > pRealSlot )
1136 {
1137 SfxStateFunc pSiblingFnc=nullptr;
1138 SfxStateCache *pSiblingCache =
1139 GetStateCache( pSibling->GetSlotId(), &nCachePos );
1140
1141 // Is the slot cached ?
1142 if ( pSiblingCache )
1143 {
1144 const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImpl->xProv);
1145 if ( pServ && pServ->GetShellLevel() == nShellLevel )
1146 pSiblingFnc = pServ->GetSlot()->GetStateFnc();
1147 }
1148
1149 // Does the slot have to be updated at all?
1150 bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
1151
1152 // It is not enough to ask for the same shell!!
1153 bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
1154
1155 if ( bInsert && bSameMethod )
1156 {
1157 SfxFoundCache_Impl aFoundCache(
1158 pSibling->GetWhich(rPool),
1159 pSibling, *pSiblingCache);
1160
1161 rFound.push_back( aFoundCache );
1162 }
1163
1164 pSibling = pSibling->GetNextSlot();
1165 }
1166
1167 // Create a Set from the ranges
1168 WhichRangesContainer ranges;
1169 size_t i = 0;
1170 while ( i < rFound.size() )
1171 {
1172 const sal_uInt16 nWhich1 = rFound[i].nWhichId;
1173 // consecutive numbers
1174 for ( ; i < rFound.size()-1; ++i )
1175 if ( rFound[i].nWhichId+1 != rFound[i+1].nWhichId )
1176 break;
1177 const sal_uInt16 nWhich2 = rFound[i++].nWhichId;
1178 ranges = ranges.MergeRange(nWhich1, nWhich2);
1179 }
1180 SfxItemSet aSet(rPool, std::move(ranges));
1181 return aSet;
1182}
1183
1184
1186(
1187 const SfxFoundCache_Impl& rFound, // Cache, Slot, Which etc.
1188 const SfxPoolItem* pItem, // item to send to controller
1189 SfxItemState eState // state of item
1190)
1191{
1192 SfxStateCache& rCache = rFound.rCache;
1193 const SfxSlot* pSlot = rFound.pSlot;
1194 DBG_ASSERT( !pSlot || rCache.GetId() == pSlot->GetSlotId(), "SID mismatch" );
1195
1196 // bound until now, the Controller to update the Slot.
1197 if (!rCache.IsControllerDirty())
1198 return;
1199
1200 if ( SfxItemState::DONTCARE == eState )
1201 {
1202 // ambiguous
1203 rCache.SetState( SfxItemState::DONTCARE, INVALID_POOL_ITEM );
1204 }
1205 else if ( SfxItemState::DEFAULT == eState &&
1207 {
1208 // no Status or Default but without Pool
1209 SfxVoidItem aVoid(0);
1210 rCache.SetState( SfxItemState::UNKNOWN, &aVoid );
1211 }
1212 else if ( SfxItemState::DISABLED == eState )
1213 rCache.SetState(SfxItemState::DISABLED, nullptr);
1214 else
1215 rCache.SetState(SfxItemState::DEFAULT, pItem);
1216}
1217
1218IMPL_LINK( SfxBindings, NextJob, Timer *, pTimer, void )
1219{
1220 NextJob_Impl(pTimer);
1221}
1222
1224{
1225 const unsigned MAX_INPUT_DELAY = 200;
1226
1227 if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer )
1228 {
1229 pImpl->aAutoTimer.SetTimeout(TIMEOUT_UPDATING);
1230 return true;
1231 }
1232
1233 SfxApplication *pSfxApp = SfxGetpApp();
1234
1235 if( pDispatcher )
1237
1238 // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1239 SfxViewFrame* pFrame = pDispatcher ? pDispatcher->GetFrame() : nullptr;
1240 if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || pImpl->pCaches.empty() )
1241 {
1242 return true;
1243 }
1244 if ( !pDispatcher || !pDispatcher->IsFlushed() )
1245 {
1246 return true;
1247 }
1248
1249 // if possible Update all server / happens in its own time slice
1250 if ( pImpl->bMsgDirty )
1251 {
1253 return false;
1254 }
1255
1256 pImpl->bAllDirty = false;
1257 pImpl->aAutoTimer.SetTimeout(TIMEOUT_UPDATING);
1258
1259 // at least 10 loops and further if more jobs are available but no input
1260 bool bPreEmptive = pTimer;
1261 sal_uInt16 nLoops = 10;
1262 pImpl->bInNextJob = true;
1263 const std::size_t nCount = pImpl->pCaches.size();
1264 while ( pImpl->nMsgPos < nCount )
1265 {
1266 // iterate through the bound functions
1267 bool bJobDone = false;
1268 while ( !bJobDone )
1269 {
1270 SfxStateCache* pCache = pImpl->pCaches[pImpl->nMsgPos].get();
1271 DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
1272 bool bWasDirty = pCache->IsControllerDirty();
1273 if ( bWasDirty )
1274 {
1275 Update_Impl(*pCache);
1276 DBG_ASSERT(nCount == pImpl->pCaches.size(), "Reschedule in StateChanged => buff");
1277 }
1278
1279 // skip to next function binding
1280 ++pImpl->nMsgPos;
1281
1282 // keep job if it is not completed, but any input is available
1283 bJobDone = pImpl->nMsgPos >= nCount;
1284 if ( bJobDone && pImpl->bFirstRound )
1285 {
1286
1287 // Update of the preferred shell has been done, now may
1288 // also the others shells be updated
1289 bJobDone = false;
1290 pImpl->bFirstRound = false;
1291 pImpl->nMsgPos = 0;
1292 }
1293
1294 if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
1295 {
1296 pImpl->bInNextJob = false;
1297 return false;
1298 }
1299 }
1300 }
1301
1302 pImpl->nMsgPos = 0;
1303
1304 pImpl->aAutoTimer.Stop();
1305
1306 // Update round is finished
1307 pImpl->bInNextJob = false;
1308 Broadcast(SfxHint(SfxHintId::UpdateDone));
1309 return true;
1310}
1311
1312
1313sal_uInt16 SfxBindings::EnterRegistrations(std::string_view pFile, int nLine)
1314{
1315 SAL_INFO(
1316 "sfx.control",
1317 std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
1318 << " Level = " << nRegLevel << " SfxBindings::EnterRegistrations "
1319 << (!pFile.empty()
1320 ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
1321
1322 // When bindings are locked, also lock sub bindings.
1323 if ( pImpl->pSubBindings )
1324 {
1325 pImpl->pSubBindings->ENTERREGISTRATIONS();
1326
1327 // These EnterRegistrations are not "real" for the SubBindings
1328 pImpl->pSubBindings->pImpl->nOwnRegLevel--;
1329
1330 // Synchronize Bindings
1331 pImpl->pSubBindings->nRegLevel = nRegLevel + pImpl->pSubBindings->pImpl->nOwnRegLevel + 1;
1332 }
1333
1334 pImpl->nOwnRegLevel++;
1335
1336 // check if this is the outer most level
1337 if ( ++nRegLevel == 1 )
1338 {
1339 // stop background-processing
1340 pImpl->aAutoTimer.Stop();
1341
1342 // flush the cache
1343 pImpl->nCachedFunc1 = 0;
1344 pImpl->nCachedFunc2 = 0;
1345
1346 // Mark if the all of the Caches have disappeared.
1347 pImpl->bCtrlReleased = false;
1348 }
1349
1350 return nRegLevel;
1351}
1352
1353
1354void SfxBindings::LeaveRegistrations( std::string_view pFile, int nLine )
1355{
1356 DBG_ASSERT( nRegLevel, "Leave without Enter" );
1357
1358 // Only when the SubBindings are still locked by the Superbindings,
1359 // remove this lock (i.e. if there are more locks than "real" ones)
1360 if ( pImpl->pSubBindings && pImpl->pSubBindings->nRegLevel > pImpl->pSubBindings->pImpl->nOwnRegLevel )
1361 {
1362 // Synchronize Bindings
1363 pImpl->pSubBindings->nRegLevel = nRegLevel + pImpl->pSubBindings->pImpl->nOwnRegLevel;
1364
1365 // This LeaveRegistrations is not "real" for SubBindings
1366 pImpl->pSubBindings->pImpl->nOwnRegLevel++;
1367 pImpl->pSubBindings->LEAVEREGISTRATIONS();
1368 }
1369
1370 pImpl->nOwnRegLevel--;
1371
1372 // check if this is the outer most level
1373 if ( --nRegLevel == 0 && SfxGetpApp() && !SfxGetpApp()->IsDowning() )
1374 {
1375 if ( pImpl->bContextChanged )
1376 {
1377 pImpl->bContextChanged = false;
1378 }
1379
1380 SfxViewFrame* pFrame = pDispatcher->GetFrame();
1381
1382 // If possible remove unused Caches, for example prepare PlugInInfo
1383 if ( pImpl->bCtrlReleased )
1384 {
1385 for ( sal_uInt16 nCache = pImpl->pCaches.size(); nCache > 0; --nCache )
1386 {
1387 // Get Cache via css::sdbcx::Index
1388 SfxStateCache *pCache = pImpl->pCaches[nCache-1].get();
1389
1390 // No interested Controller present
1391 if ( pCache->GetItemLink() == nullptr && !pCache->GetInternalController() )
1392 {
1393 // Remove Cache. Safety: first remove and then delete
1394 pImpl->pCaches.erase(pImpl->pCaches.begin() + nCache - 1);
1395 }
1396 }
1397 }
1398
1399 // restart background-processing
1400 pImpl->nMsgPos = 0;
1401 if ( !pFrame || !pFrame->GetObjectShell() )
1402 return;
1403 if ( !pImpl->pCaches.empty() )
1404 {
1405 pImpl->aAutoTimer.Stop();
1406 pImpl->aAutoTimer.SetTimeout(TIMEOUT_FIRST);
1407 pImpl->aAutoTimer.Start();
1408 }
1409 }
1410
1411 SAL_INFO(
1412 "sfx.control",
1413 std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
1414 << " Level = " << nRegLevel << " SfxBindings::LeaveRegistrations "
1415 << (!pFile.empty()
1416 ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
1417}
1418
1419
1421{
1422 SfxDispatcher *pOldDispat = pDispatcher;
1423 if ( pDisp == pDispatcher )
1424 return;
1425
1426 if ( pOldDispat )
1427 {
1428 SfxBindings* pBind = pOldDispat->GetBindings();
1429 while ( pBind )
1430 {
1431 if ( pBind->pImpl->pSubBindings == this && pBind->pDispatcher != pDisp )
1432 pBind->SetSubBindings_Impl( nullptr );
1433 pBind = pBind->pImpl->pSubBindings;
1434 }
1435 }
1436
1437 pDispatcher = pDisp;
1438
1439 css::uno::Reference < css::frame::XDispatchProvider > xProv;
1440 if ( pDisp )
1441 xProv.set( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1442
1443 SetDispatchProvider_Impl( xProv );
1444 InvalidateAll( true );
1445
1446 if ( pDispatcher && !pOldDispat )
1447 {
1448 if ( pImpl->pSubBindings && pImpl->pSubBindings->pDispatcher != pOldDispat )
1449 {
1450 OSL_FAIL( "SubBindings already set before activating!" );
1451 pImpl->pSubBindings->ENTERREGISTRATIONS();
1452 }
1454 }
1455 else if( !pDispatcher )
1456 {
1458 if ( pImpl->pSubBindings && pImpl->pSubBindings->pDispatcher != pOldDispat )
1459 {
1460 OSL_FAIL( "SubBindings still set even when deactivating!" );
1461 pImpl->pSubBindings->LEAVEREGISTRATIONS();
1462 }
1463 }
1464
1465 Broadcast( SfxHint( SfxHintId::DataChanged ) );
1466
1467 if ( !pDisp )
1468 return;
1469
1470 SfxBindings* pBind = pDisp->GetBindings();
1471 while ( pBind && pBind != this )
1472 {
1473 if ( !pBind->pImpl->pSubBindings )
1474 {
1475 pBind->SetSubBindings_Impl( this );
1476 break;
1477 }
1478
1479 pBind = pBind->pImpl->pSubBindings;
1480 }
1481}
1482
1483
1484void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
1485{
1486 SfxStateCache* pCache = GetStateCache(nSlotId);
1487 if (!pCache)
1488 return;
1489 pCache->ClearCache();
1490}
1491
1492
1493void SfxBindings::StartUpdate_Impl( bool bComplete )
1494{
1495 if ( pImpl->pSubBindings )
1496 pImpl->pSubBindings->StartUpdate_Impl( bComplete );
1497
1498 if ( !bComplete )
1499 // Update may be interrupted
1500 NextJob_Impl(&pImpl->aAutoTimer);
1501 else
1502 // Update all slots in a row
1503 NextJob_Impl(nullptr);
1504}
1505
1506
1507SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, std::unique_ptr<SfxPoolItem> &rpState )
1508{
1509 css::uno::Reference< css::frame::XDispatch > xDisp;
1510 SfxStateCache *pCache = GetStateCache( nSlot );
1511 if ( pCache )
1512 xDisp = pCache->GetDispatch();
1513 if ( xDisp.is() || !pCache )
1514 {
1515 const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot );
1516 if ( !pSlot || pSlot->pUnoName.isEmpty() )
1517 return SfxItemState::DISABLED;
1518
1519 css::util::URL aURL;
1520 OUString aCmd( ".uno:" );
1521 aURL.Protocol = aCmd;
1522 aURL.Path = pSlot->GetUnoName();
1523 aCmd += aURL.Path;
1524 aURL.Complete = aCmd;
1525 aURL.Main = aCmd;
1526
1527 if ( !xDisp.is() )
1528 xDisp = pImpl->xProv->queryDispatch( aURL, OUString(), 0 );
1529
1530 if ( xDisp.is() )
1531 {
1532 if (!dynamic_cast<SfxOfficeDispatch*>(xDisp.get()))
1533 {
1534 bool bDeleteCache = false;
1535 if ( !pCache )
1536 {
1537 pCache = new SfxStateCache( nSlot );
1538 pCache->GetSlotServer( *GetDispatcher_Impl(), pImpl->xProv );
1539 bDeleteCache = true;
1540 }
1541
1542 SfxItemState eState = SfxItemState::SET;
1543 rtl::Reference<BindDispatch_Impl> xBind(new BindDispatch_Impl( xDisp, aURL, pCache, pSlot ));
1544 xDisp->addStatusListener( xBind, aURL );
1545 if ( !xBind->GetStatus().IsEnabled )
1546 {
1547 eState = SfxItemState::DISABLED;
1548 }
1549 else
1550 {
1551 css::uno::Any aAny = xBind->GetStatus().State;
1552 const css::uno::Type& aType = aAny.getValueType();
1553
1554 if ( aType == cppu::UnoType<bool>::get() )
1555 {
1556 bool bTemp = false;
1557 aAny >>= bTemp ;
1558 rpState.reset(new SfxBoolItem( nSlot, bTemp ));
1559 }
1561 {
1562 sal_uInt16 nTemp = 0;
1563 aAny >>= nTemp ;
1564 rpState.reset(new SfxUInt16Item( nSlot, nTemp ));
1565 }
1566 else if ( aType == cppu::UnoType<sal_uInt32>::get() )
1567 {
1568 sal_uInt32 nTemp = 0;
1569 aAny >>= nTemp ;
1570 rpState.reset(new SfxUInt32Item( nSlot, nTemp ));
1571 }
1572 else if ( aType == cppu::UnoType<OUString>::get() )
1573 {
1574 OUString sTemp ;
1575 aAny >>= sTemp ;
1576 rpState.reset(new SfxStringItem( nSlot, sTemp ));
1577 }
1578 else
1579 rpState.reset(new SfxVoidItem( nSlot ));
1580 }
1581
1582 xDisp->removeStatusListener( xBind, aURL );
1583 xBind->Release();
1584 xBind.clear();
1585 if ( bDeleteCache )
1586 {
1587 delete pCache;
1588 pCache = nullptr;
1589 }
1590 return eState;
1591 }
1592 }
1593 }
1594
1595 // Then test at the dispatcher to check if the returned items from
1596 // there are always DELETE_ON_IDLE, a copy of it has to be made in
1597 // order to allow for transition of ownership.
1598 const SfxPoolItem *pItem = nullptr;
1599 SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
1600 if ( eState == SfxItemState::SET )
1601 {
1602 DBG_ASSERT( pItem, "SfxItemState::SET but no item!" );
1603 if ( pItem )
1604 rpState.reset(pItem->Clone());
1605 }
1606 else if ( eState == SfxItemState::DEFAULT && pItem )
1607 {
1608 rpState.reset(pItem->Clone());
1609 }
1610
1611 return eState;
1612}
1613
1614void SfxBindings::QueryControlState( sal_uInt16 nSlot, boost::property_tree::ptree& rState )
1615{
1616 if ( SfxGetpApp()->IsDowning() )
1617 return;
1618
1619 if ( pDispatcher )
1620 pDispatcher->Flush();
1621
1622 if ( pImpl->pSubBindings )
1623 pImpl->pSubBindings->QueryControlState( nSlot, rState );
1624
1625 SfxStateCache* pCache = GetStateCache( nSlot );
1626 if ( !pCache )
1627 return;
1628
1629 if ( pImpl->bMsgDirty )
1630 {
1632 pCache = GetStateCache( nSlot );
1633 }
1634
1635 if (pCache && pCache->GetItemLink() )
1636 {
1637 pCache->GetState(rState);
1638 }
1639}
1640
1641sal_uInt16 SfxBindings::QuerySlotId( const util::URL& aURL )
1642{
1643 if (!pImpl)
1644 return 0;
1645
1646 css::uno::Reference<css::frame::XDispatch> xDispatch =
1647 pImpl->xProv->queryDispatch(aURL, OUString(), 0);
1648 if (!xDispatch.is())
1649 return 0;
1650
1651 SfxOfficeDispatch* pDispatch = dynamic_cast<SfxOfficeDispatch*>(xDispatch.get());
1652 if (!pDispatch)
1653 return 0;
1654
1655 return pDispatch->GetId();
1656}
1657
1659{
1660 if ( pImpl->pSubBindings )
1661 {
1662 pImpl->pSubBindings->SetDispatchProvider_Impl( css::uno::Reference< css::frame::XDispatchProvider > () );
1663 }
1664
1665 pImpl->pSubBindings = pSub;
1666
1667 if ( pSub )
1668 {
1669 pImpl->pSubBindings->SetDispatchProvider_Impl( pImpl->xProv );
1670 }
1671}
1672
1674{
1675 return pImpl->pSubBindings;
1676}
1677
1678void SfxBindings::SetWorkWindow_Impl( std::unique_ptr<SfxWorkWindow> xWork )
1679{
1680 pImpl->mxWorkWin = std::move(xWork);
1681}
1682
1684{
1685 return pImpl->mxWorkWin.get();
1686}
1687
1689{
1690 bool bInUpdate = pImpl->bInUpdate;
1691 if ( !bInUpdate && pImpl->pSubBindings )
1692 bInUpdate = pImpl->pSubBindings->IsInUpdate();
1693 return bInUpdate;
1694}
1695
1696void SfxBindings::SetVisibleState( sal_uInt16 nId, bool bShow )
1697{
1698 SfxStateCache *pCache = GetStateCache( nId );
1699 if ( pCache )
1700 pCache->SetVisibleState( bShow );
1701}
1702
1703void SfxBindings::SetActiveFrame( const css::uno::Reference< css::frame::XFrame > & rFrame )
1704{
1705 if ( rFrame.is() || !pDispatcher )
1706 SetDispatchProvider_Impl( css::uno::Reference< css::frame::XDispatchProvider > ( rFrame, css::uno::UNO_QUERY ) );
1707 else
1708 SetDispatchProvider_Impl( css::uno::Reference< css::frame::XDispatchProvider > (
1709 pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), css::uno::UNO_QUERY ) );
1710}
1711
1712css::uno::Reference< css::frame::XFrame > SfxBindings::GetActiveFrame() const
1713{
1714 const css::uno::Reference< css::frame::XFrame > xFrame( pImpl->xProv, css::uno::UNO_QUERY );
1715 if ( xFrame.is() || !pDispatcher )
1716 return xFrame;
1717 else
1719}
1720
1721void SfxBindings::SetDispatchProvider_Impl( const css::uno::Reference< css::frame::XDispatchProvider > & rProv )
1722{
1723 bool bInvalidate = ( rProv != pImpl->xProv );
1724 if ( bInvalidate )
1725 {
1726 pImpl->xProv = rProv;
1727 InvalidateAll( true );
1728 }
1729
1730 if ( pImpl->pSubBindings )
1731 pImpl->pSubBindings->SetDispatchProvider_Impl( pImpl->xProv );
1732}
1733
1734const css::uno::Reference< css::frame::XDispatchRecorder >& SfxBindings::GetRecorder() const
1735{
1736 return pImpl->xRecorder;
1737}
1738
1739void SfxBindings::SetRecorder_Impl( css::uno::Reference< css::frame::XDispatchRecorder > const & rRecorder )
1740{
1741 pImpl->xRecorder = rRecorder;
1742}
1743
1745{
1746 if ( !pImpl->bInUpdate && ( !pImpl->bContextChanged || !pImpl->bAllMsgDirty ) )
1747 {
1748 InvalidateAll( true );
1749 }
1750}
1751
1752uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, bool bMasterCommand )
1753{
1754 uno::Reference < frame::XDispatch > xRet;
1755 SfxStateCache* pCache = GetStateCache( pSlot->nSlotId );
1756 if ( pCache && !bMasterCommand )
1757 xRet = pCache->GetInternalDispatch();
1758 if ( !xRet.is() )
1759 {
1760 // dispatches for slaves are unbound, they don't have a state
1761 SfxOfficeDispatch* pDispatch = bMasterCommand ?
1762 new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) :
1763 new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL );
1764
1765 pDispatch->SetMasterUnoCommand( bMasterCommand );
1766 xRet.set( pDispatch );
1767 if ( !pCache )
1768 pCache = GetStateCache( pSlot->nSlotId );
1769
1770 DBG_ASSERT( pCache, "No cache for OfficeDispatch!" );
1771 if ( pCache && !bMasterCommand )
1772 pCache->SetInternalDispatch( xRet );
1773 }
1774
1775 return xRet;
1776}
1777
1778/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxApplication * SfxGetpApp()
Definition: app.hxx:231
#define TIMEOUT_FIRST
Definition: bindings.cxx:64
#define TIMEOUT_UPDATING
Definition: bindings.cxx:65
IMPL_LINK(SfxBindings, NextJob, Timer *, pTimer, void)
Definition: bindings.cxx:1218
#define ENTERREGISTRATIONS()
Definition: bindings.hxx:193
#define LEAVEREGISTRATIONS()
Definition: bindings.hxx:194
SfxCallMode
Definition: bindings.hxx:57
static sal_uInt64 GetLastInputInterval()
bool IsDowning() const
Definition: appmisc.cxx:102
sal_uInt16 nOwnRegLevel
Definition: bindings.cxx:122
std::size_t nCachedFunc1
Definition: bindings.cxx:110
AutoTimer aAutoTimer
Definition: bindings.cxx:118
std::unique_ptr< SfxWorkWindow > mxWorkWin
Definition: bindings.cxx:107
css::uno::Reference< css::frame::XDispatchRecorder > xRecorder
Definition: bindings.cxx:105
css::uno::Reference< css::frame::XDispatchProvider > xProv
Definition: bindings.cxx:106
std::vector< std::unique_ptr< SfxStateCache > > pCaches
Definition: bindings.cxx:109
std::size_t nMsgPos
Definition: bindings.cxx:112
std::unordered_map< sal_uInt16, bool > m_aInvalidateSlots
Definition: bindings.cxx:124
std::size_t nCachedFunc2
Definition: bindings.cxx:111
SfxBindings * pSubBindings
Definition: bindings.cxx:108
void SetVisibleState(sal_uInt16 nId, bool bShow)
Definition: bindings.cxx:1696
SfxDispatcher * pDispatcher
Definition: bindings.hxx:98
SAL_DLLPRIVATE SfxStateCache * GetStateCache(sal_uInt16 nId, std::size_t *pPos)
Definition: bindings.cxx:474
SAL_DLLPRIVATE void SetSubBindings_Impl(SfxBindings *)
Definition: bindings.cxx:1658
void LeaveRegistrations(std::string_view pFile={}, int nLine=0)
Definition: bindings.cxx:1354
SAL_DLLPRIVATE SfxWorkWindow * GetWorkWindow_Impl() const
Definition: bindings.cxx:1683
std::unique_ptr< SfxBindings_Impl > pImpl
Definition: bindings.hxx:97
void SetState(const SfxItemSet &rSet)
Definition: bindings.cxx:383
SAL_DLLPRIVATE SfxDispatcher * GetDispatcher_Impl()
Definition: bindings.hxx:180
void QueryControlState(sal_uInt16 nSID, boost::property_tree::ptree &rState)
Definition: bindings.cxx:1614
SAL_DLLPRIVATE void StartUpdate_Impl(bool bComplete=false)
Definition: bindings.cxx:1493
SAL_DLLPRIVATE void SetDispatchProvider_Impl(const css::uno::Reference< css::frame::XDispatchProvider > &rFrame)
Definition: bindings.cxx:1721
SAL_DLLPRIVATE std::optional< SfxItemSet > CreateSet_Impl(SfxStateCache &rCache, const SfxSlot *&pRealSlot, const SfxSlotServer **, SfxFoundCacheArr_Impl &)
Definition: bindings.cxx:1094
void InvalidateShell(const SfxShell &rSh, bool bDeep=false)
Definition: bindings.cxx:585
sal_uInt16 EnterRegistrations(std::string_view pFile={}, int nLine=0)
Definition: bindings.cxx:1313
SfxItemState QueryState(sal_uInt16 nSID, std::unique_ptr< SfxPoolItem > &rpState)
Definition: bindings.cxx:1507
SAL_DLLPRIVATE void SetWorkWindow_Impl(std::unique_ptr< SfxWorkWindow >)
Definition: bindings.cxx:1678
sal_uInt16 QuerySlotId(const css::util::URL &aURL)
Definition: bindings.cxx:1641
SAL_DLLPRIVATE const SfxPoolItem * Execute_Impl(sal_uInt16 nSlot, const SfxPoolItem **pArgs, sal_uInt16 nModi, SfxCallMode nCall, const SfxPoolItem **pInternalArgs, bool bGlobalOnly=false)
Definition: bindings.cxx:875
SAL_DLLPRIVATE void AddSlotToInvalidateSlotsMap_Impl(sal_uInt16 nId)
Definition: bindings.cxx:295
bool Execute(sal_uInt16 nSlot, const SfxPoolItem **pArgs=nullptr, SfxCallMode nCall=SfxCallMode::SLOT)
Definition: bindings.cxx:866
SAL_DLLPRIVATE void DeleteControllers_Impl()
Definition: bindings.cxx:183
SAL_DLLPRIVATE void InvalidateSlotsInMap_Impl()
Definition: bindings.cxx:286
const SfxPoolItem * ExecuteSynchron(sal_uInt16 nSlot, const SfxPoolItem **pArgs=nullptr)
Definition: bindings.cxx:858
SAL_DLLPRIVATE SfxStateCache * GetAnyStateCache_Impl(sal_uInt16 nId)
Definition: bindings.cxx:457
css::uno::Reference< css::frame::XDispatch > GetDispatch(const SfxSlot *, const css::util::URL &aURL, bool bMasterCommand)
Definition: bindings.cxx:1752
SAL_DLLPRIVATE bool NextJob_Impl(Timer const *pTimer)
Definition: bindings.cxx:1223
SfxDispatcher * GetDispatcher() const
Definition: bindings.hxx:172
void Invalidate(sal_uInt16 nId)
Definition: bindings.cxx:639
SAL_DLLPRIVATE std::size_t GetSlotPos(sal_uInt16 nId, std::size_t nStartSearchAt=0)
Definition: bindings.cxx:708
css::uno::Reference< css::frame::XFrame > GetActiveFrame() const
Definition: bindings.cxx:1712
SAL_DLLPRIVATE void RegisterInternal_Impl(SfxControllerItem &rBinding)
Definition: bindings.cxx:769
void Register(SfxControllerItem &rBinding)
Definition: bindings.cxx:775
SAL_DLLPRIVATE void UpdateSlotServer_Impl()
Definition: bindings.cxx:1067
const css::uno::Reference< css::frame::XDispatchRecorder > & GetRecorder() const
Definition: bindings.cxx:1734
SAL_DLLPRIVATE void Register_Impl(SfxControllerItem &rBinding, bool)
Definition: bindings.cxx:780
void Release(SfxControllerItem &rBinding)
Definition: bindings.cxx:814
SAL_DLLPRIVATE void Update_Impl(SfxStateCache &rCache)
Definition: bindings.cxx:238
SAL_DLLPRIVATE void ContextChanged_Impl()
Definition: bindings.cxx:1744
void HidePopups(bool bHide=true)
Definition: bindings.cxx:230
sal_uInt16 nRegLevel
Definition: bindings.hxx:99
SAL_DLLPRIVATE void SetRecorder_Impl(css::uno::Reference< css::frame::XDispatchRecorder > const &)
Definition: bindings.cxx:1739
SAL_DLLPRIVATE SfxBindings * GetSubBindings_Impl() const
Definition: bindings.cxx:1673
SAL_DLLPRIVATE void ClearCache_Impl(sal_uInt16 nSlotId)
Definition: bindings.cxx:1484
static SAL_DLLPRIVATE void UpdateControllers_Impl(const SfxFoundCache_Impl &rFound, const SfxPoolItem *pItem, SfxItemState eItemState)
Definition: bindings.cxx:1186
void SetActiveFrame(const css::uno::Reference< css::frame::XFrame > &rFrame)
Definition: bindings.cxx:1703
void SetDispatcher(SfxDispatcher *pDisp)
Definition: bindings.cxx:1420
void InvalidateAll(bool bWithMsg)
Definition: bindings.cxx:498
void Update()
Definition: bindings.cxx:361
virtual ~SfxBindings() override
Definition: bindings.cxx:153
bool IsInUpdate() const
Definition: bindings.cxx:1688
void Broadcast(const SfxHint &rHint)
SfxControllerItem * ChangeItemLink(SfxControllerItem *pNewLink)
Definition: ctrlitem.cxx:156
sal_uInt16 GetId() const
Definition: ctrlitem.hxx:63
SfxControllerItem * GetItemLink()
Definition: ctrlitem.cxx:31
SAL_DLLPRIVATE void Update_Impl(bool bForce=false)
Definition: dispatch.cxx:1034
bool IsFlushed() const
This method checks if the stack of the SfxDispatchers is flushed, or if push- or pop- commands are pe...
Definition: dispatch.cxx:145
SfxBindings * GetBindings() const
This method returns a pointer to the <SfxBinding> Instance on which the SfxDispatcher is currently bo...
Definition: dispatch.cxx:545
bool FillState_(const SfxSlotServer &rServer, SfxItemSet &rState, const SfxSlot *pRealSlot)
Helper method to obtain the status of the <Slot-Server>s rSvr.
Definition: dispatch.cxx:1655
sal_uInt16 GetShellLevel(const SfxShell &rShell)
Determines the position of a given SfxShell in the stack of the dispatcher.
Definition: dispatch.cxx:510
SfxViewFrame * GetFrame() const
Returns a pointer to the <SfxViewFrame> instance, which belongs to this SfxDispatcher.
Definition: dispatch.cxx:557
SfxShell * GetShell(sal_uInt16 nIdx) const
Returns a pointer to the <SfxShell> which is at the position nIdx (from the top, last pushed is 0) on...
Definition: dispatch.cxx:529
void Execute_(SfxShell &rShell, const SfxSlot &rSlot, SfxRequest &rReq, SfxCallMode eCall)
This method performs a request for a cached <Slot-Server>.
Definition: dispatch.cxx:726
SfxItemState QueryState(sal_uInt16 nSID, const SfxPoolItem *&rpState)
Definition: dispatch.cxx:1970
void Flush()
This method performs outstanding push- and pop- commands.
Definition: dispatch.cxx:155
SfxFoundCache_Impl & operator[](size_t i)
Definition: bindings.cxx:86
size_t size() const
Definition: bindings.cxx:91
std::vector< SfxFoundCache_Impl > maData
Definition: bindings.cxx:82
void push_back(SfxFoundCache_Impl p)
Definition: bindings.cxx:96
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
Definition: frame.cxx:515
const SfxPoolItem * GetCurItem() const
const SfxPoolItem * NextItem()
sal_uInt16 GetSlotId(sal_uInt16 nWhich) const
static bool IsWhich(sal_uInt16 nId)
static bool IsSlot(sal_uInt16 nId)
SfxItemPool * GetPool() const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
bool AcceptStateUpdate() const
Definition: objmisc.cxx:427
sal_uInt16 GetId() const
Definition: unoctitm.cxx:288
void SetMasterUnoCommand(bool bSet)
Definition: unoctitm.cxx:299
sal_uInt16 Which() const
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const=0
const SfxPoolItem * GetReturnValue() const
Definition: request.cxx:429
const SfxItemSet * GetArgs() const
Definition: request.hxx:75
void SetSlot(sal_uInt16 nNewSlot)
Definition: request.hxx:69
void AppendItem(const SfxPoolItem &)
Definition: request.cxx:404
SfxCallMode GetCallMode() const
Definition: request.cxx:289
void SetModifier(sal_uInt16 nModi)
Definition: request.cxx:718
void SetInternalArgs_Impl(const SfxAllItemSet &rArgs)
Definition: request.cxx:309
The class SfxShell is the base class for all classes, which provide the functionality of the form <Sl...
Definition: shell.hxx:128
SfxItemPool & GetPool() const
Each Subclass of SfxShell must reference a pool.
Definition: shell.hxx:511
static SfxSlotPool & GetSlotPool(SfxViewFrame *pFrame=nullptr)
Definition: msgpool.cxx:316
const SfxSlot * GetSlot(sal_uInt16 nId) const
Definition: msgpool.cxx:155
const SfxSlot * GetSlot() const
Definition: slotserv.hxx:52
sal_uInt16 GetShellLevel() const
Definition: slotserv.hxx:47
Definition: msg.hxx:184
sal_uInt16 GetSlotId() const
Definition: msg.hxx:253
OUString pUnoName
Definition: msg.hxx:205
const SfxType * GetType() const
Definition: msg.hxx:236
const SfxSlot * GetNextSlot() const
Definition: msg.hxx:247
const OUString & GetUnoName() const
Definition: msg.hxx:237
SfxStateFunc GetStateFnc() const
Definition: msg.hxx:245
sal_uInt16 nSlotId
Definition: msg.hxx:186
bool IsMode(SfxSlotMode nMode) const
Definition: msg.hxx:268
SfxSlotKind GetKind() const
Definition: msg.cxx:25
sal_uInt16 GetWhich(const SfxItemPool &rPool) const
Definition: msg.cxx:39
const css::uno::Reference< css::frame::XDispatch > & GetInternalDispatch() const
Definition: statcach.hxx:109
void Invalidate(bool bWithSlot)
Definition: statcach.cxx:211
SfxControllerItem * GetItemLink() const
Definition: statcach.hxx:141
SfxControllerItem * ChangeItemLink(SfxControllerItem *pNewBinding)
Definition: statcach.hxx:126
bool IsControllerDirty() const
Definition: statcach.hxx:92
sal_uInt16 GetId() const
Definition: statcach.hxx:147
void ClearCache()
Definition: statcach.hxx:118
css::uno::Reference< css::frame::XDispatch > GetDispatch() const
Definition: statcach.cxx:477
void SetState(SfxItemState, const SfxPoolItem *, bool bMaybeDirty=false)
Definition: statcach.cxx:311
void SetCachedState(bool bAlways)
Definition: statcach.cxx:450
SfxControllerItem * GetInternalController() const
Definition: statcach.hxx:107
const SfxSlotServer * GetSlotServer(SfxDispatcher &rDispat, const css::uno::Reference< css::frame::XDispatchProvider > &xProv)
Definition: statcach.cxx:227
void SetInternalDispatch(const css::uno::Reference< css::frame::XDispatch > &rDisp)
Definition: statcach.hxx:111
void ReleaseInternalController()
Definition: statcach.hxx:106
void SetVisibleState(bool bShow)
Definition: statcach.cxx:342
void GetState(boost::property_tree::ptree &)
Definition: statcach.cxx:329
sal_Int16 Dispatch(const SfxItemSet *pSet, bool bForceSynchron)
Definition: statcach.cxx:484
SfxFrame & GetFrame() const
Definition: viewfrm.cxx:2782
virtual SfxObjectShell * GetObjectShell() override
Definition: viewfrm.cxx:2218
int nCount
const char * pS
#define DBG_ASSERT(sCon, aError)
Reference< XDispatch > xDispatch
URL aURL
void DeleteItemOnIdle(std::unique_ptr< SfxPoolItem > pItem)
Definition: itemdel.cxx:50
void * p
sal_Int64 n
sal_uInt16 nPos
Definition: linksrc.cxx:118
#define SAL_STREAM(stream)
#define SAL_INFO(area, stream)
int i
sal_Int16 nId
#define INVALID_POOL_ITEM
SfxItemState
static SfxItemSet & rSet
Definition: shell.cxx:534
void(* SfxStateFunc)(SfxShell *, SfxItemSet &rSet)
Definition: shell.hxx:112
const SfxSlot * pSlot
Definition: bindings.cxx:70
SfxStateCache & rCache
Definition: bindings.cxx:71
SfxFoundCache_Impl(sal_uInt16 nW, const SfxSlot *pS, SfxStateCache &rC)
Definition: bindings.cxx:73
sal_uInt16 nWhichId
Definition: bindings.cxx:69
std::unique_ptr< SfxPoolItem > CreateItem() const
Definition: msg.hxx:111
SAL_WARN_UNUSED_RESULT WhichRangesContainer MergeRange(sal_uInt16 nFrom, sal_uInt16 nTo) const
Reference< XFrame > xFrame