bump product version to 6.3.0.0.beta1
[LibreOffice.git] / svl / source / notify / SfxBroadcaster.cxx
blob2e312a80ce8512d9ed3acea57bd8d1bbeaa3a583
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svl/SfxBroadcaster.hxx>
22 #include <svl/hint.hxx>
23 #include <svl/lstner.hxx>
24 #include <tools/debug.hxx>
26 #include <algorithm>
27 #include <cassert>
28 #include <vector>
31 typedef std::vector<SfxListener*> SfxListenerArr_Impl;
33 struct SfxBroadcaster::Impl
35 /** Contains the positions of removed listeners. */
36 std::vector<size_t> m_RemovedPositions;
37 SfxListenerArr_Impl m_Listeners;
40 // broadcast immediately
42 void SfxBroadcaster::Broadcast( const SfxHint &rHint )
44 // notify all registered listeners exactly once
45 for (size_t i = 0; i < mpImpl->m_Listeners.size(); ++i)
47 SfxListener *const pListener = mpImpl->m_Listeners[i];
48 if (pListener)
49 pListener->Notify( *this, rHint );
53 // unregister all listeners
55 SfxBroadcaster::~SfxBroadcaster() COVERITY_NOEXCEPT_FALSE
57 Broadcast( SfxHint(SfxHintId::Dying) );
59 // remove all still registered listeners
60 for (size_t i = 0; i < mpImpl->m_Listeners.size(); ++i)
62 SfxListener *const pListener = mpImpl->m_Listeners[i];
63 if (pListener)
64 pListener->RemoveBroadcaster_Impl(*this);
69 // simple ctor of class SfxBroadcaster
71 SfxBroadcaster::SfxBroadcaster() : mpImpl(new Impl)
76 // copy ctor of class SfxBroadcaster
79 SfxBroadcaster::SfxBroadcaster( const SfxBroadcaster &rBC ) : mpImpl(new Impl)
81 for (size_t i = 0; i < rBC.mpImpl->m_Listeners.size(); ++i)
83 SfxListener *const pListener = rBC.mpImpl->m_Listeners[i];
84 if (pListener)
85 pListener->StartListening( *this );
90 // add a new SfxListener to the list
92 void SfxBroadcaster::AddListener( SfxListener& rListener )
94 DBG_TESTSOLARMUTEX();
95 if (mpImpl->m_RemovedPositions.empty())
97 mpImpl->m_Listeners.push_back(&rListener);
99 else
101 size_t targetPosition = mpImpl->m_RemovedPositions.back();
102 mpImpl->m_RemovedPositions.pop_back();
103 assert(mpImpl->m_Listeners[targetPosition] == nullptr);
104 mpImpl->m_Listeners[targetPosition] = &rListener;
109 // forward a notification to all registered listeners
111 void SfxBroadcaster::Forward(SfxBroadcaster& rBC, const SfxHint& rHint)
113 for (size_t i = 0; i < mpImpl->m_Listeners.size(); ++i)
115 SfxListener *const pListener = mpImpl->m_Listeners[i];
116 if (pListener)
117 pListener->Notify( rBC, rHint );
122 // remove one SfxListener from the list
124 void SfxBroadcaster::RemoveListener( SfxListener& rListener )
126 DBG_TESTSOLARMUTEX();
128 // First, check the slots either side of the last removed slot, makes a significant
129 // difference when the list is large.
130 int positionOfRemovedElement = -1;
131 if (!mpImpl->m_RemovedPositions.empty())
133 auto i = mpImpl->m_RemovedPositions.back();
134 if (i < mpImpl->m_Listeners.size() - 2 && mpImpl->m_Listeners[i+1] == &rListener)
136 positionOfRemovedElement = i + 1;
138 else if (i > 0 && mpImpl->m_Listeners[i-1] == &rListener)
140 positionOfRemovedElement = i-1;
143 // then scan the whole list if we didn't find it
144 if (positionOfRemovedElement == -1)
146 SfxListenerArr_Impl::iterator aIter = std::find(
147 mpImpl->m_Listeners.begin(), mpImpl->m_Listeners.end(), &rListener);
148 positionOfRemovedElement = std::distance(mpImpl->m_Listeners.begin(), aIter);
150 // DO NOT erase the listener, set the pointer to 0
151 // because the current continuation may contain this->Broadcast
152 mpImpl->m_Listeners[positionOfRemovedElement] = nullptr;
153 mpImpl->m_RemovedPositions.push_back(positionOfRemovedElement);
156 bool SfxBroadcaster::HasListeners() const
158 return (GetListenerCount() != 0);
161 size_t SfxBroadcaster::GetListenerCount() const
163 assert(mpImpl->m_Listeners.size() >= mpImpl->m_RemovedPositions.size());
164 return mpImpl->m_Listeners.size() - mpImpl->m_RemovedPositions.size();
167 size_t SfxBroadcaster::GetSizeOfVector() const
169 return mpImpl->m_Listeners.size();
172 SfxListener* SfxBroadcaster::GetListener( size_t nNo ) const
174 return mpImpl->m_Listeners[nNo];
178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */