1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
30 // broadcast immediately
32 void SfxBroadcaster::Broadcast(const SfxHint
& rHint
)
34 // notify all registered listeners exactly once
35 for (size_t i
= 0; i
< m_Listeners
.size(); ++i
)
37 SfxListener
* const pListener
= m_Listeners
[i
];
39 pListener
->Notify(*this, rHint
);
43 // unregister all listeners
45 SfxBroadcaster::~SfxBroadcaster() COVERITY_NOEXCEPT_FALSE
47 Broadcast(SfxHint(SfxHintId::Dying
));
49 // remove all still registered listeners
50 for (size_t i
= 0; i
< m_Listeners
.size(); ++i
)
52 SfxListener
* const pListener
= m_Listeners
[i
];
54 pListener
->RemoveBroadcaster_Impl(*this);
58 // copy ctor of class SfxBroadcaster
60 SfxBroadcaster::SfxBroadcaster(const SfxBroadcaster
& rOther
)
62 for (size_t i
= 0; i
< rOther
.m_Listeners
.size(); ++i
)
64 SfxListener
* const pListener
= rOther
.m_Listeners
[i
];
66 pListener
->StartListening(*this);
70 // add a new SfxListener to the list
72 void SfxBroadcaster::AddListener(SfxListener
& rListener
)
75 if (m_RemovedPositions
.empty())
77 m_Listeners
.push_back(&rListener
);
81 size_t targetPosition
= m_RemovedPositions
.back();
82 m_RemovedPositions
.pop_back();
83 assert(m_Listeners
[targetPosition
] == nullptr);
84 m_Listeners
[targetPosition
] = &rListener
;
88 // forward a notification to all registered listeners
90 void SfxBroadcaster::Forward(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
92 for (size_t i
= 0; i
< m_Listeners
.size(); ++i
)
94 SfxListener
* const pListener
= m_Listeners
[i
];
96 pListener
->Notify(rBC
, rHint
);
100 // remove one SfxListener from the list
102 void SfxBroadcaster::RemoveListener(SfxListener
& rListener
)
104 DBG_TESTSOLARMUTEX();
106 // First, check the slots either side of the last removed slot, makes a significant
107 // difference when the list is large.
108 int positionOfRemovedElement
= -1;
109 if (!m_RemovedPositions
.empty())
111 auto i
= m_RemovedPositions
.back();
112 if (i
< m_Listeners
.size() - 2 && m_Listeners
[i
+ 1] == &rListener
)
114 positionOfRemovedElement
= i
+ 1;
116 else if (i
> 0 && m_Listeners
[i
- 1] == &rListener
)
118 positionOfRemovedElement
= i
- 1;
121 // then scan the whole list if we didn't find it
122 if (positionOfRemovedElement
== -1)
124 auto aIter
= std::find(m_Listeners
.begin(), m_Listeners
.end(), &rListener
);
125 positionOfRemovedElement
= std::distance(m_Listeners
.begin(), aIter
);
127 // DO NOT erase the listener, set the pointer to 0
128 // because the current continuation may contain this->Broadcast
129 m_Listeners
[positionOfRemovedElement
] = nullptr;
130 m_RemovedPositions
.push_back(positionOfRemovedElement
);
133 bool SfxBroadcaster::HasListeners() const { return (GetListenerCount() != 0); }
135 size_t SfxBroadcaster::GetListenerCount() const
137 assert(m_Listeners
.size() >= m_RemovedPositions
.size());
138 return m_Listeners
.size() - m_RemovedPositions
.size();
141 size_t SfxBroadcaster::GetSizeOfVector() const { return m_Listeners
.size(); }
143 SfxListener
* SfxBroadcaster::GetListener(size_t nNo
) const { return m_Listeners
[nNo
]; }
145 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */