~ubuntu-branches/ubuntu/trusty/fluxbox/trusty-proposed

« back to all changes in this revision

Viewing changes to src/FbTk/Signal.hh

  • Committer: Package Import Robot
  • Author(s): Paul Tagliamonte
  • Date: 2010-08-12 21:16:02 UTC
  • mfrom: (0.1.1) (1.1.10)
  • Revision ID: package-import@ubuntu.com-20100812211602-3tsmzl9in5nmwz7z
Tags: 1.1.1+git20100807.0cc08f9-1
* debian/ dir has been cleaned out, complete repackage
  of most files.
* pulled new archive from git.fluxbox.org HEAD, saved as
  tar.gz.
* Added in fluxbox.* files from the old dfsg tree.
* Added in system.fluxbox-menu file from the old dfsg tree
* Added the source/format file to bump package source
  version from 1.0 to 3.0 (quilt). 
* Changed rules file to match the old dfsg setup so that
  fluxbox behaves nicely.
* Removed entries from copyright that no longer apply.
* Added theme based on Denis Brand ( naran )'s old theme.
* Added a background I whipped up.
* Changed compile flags to point to debian theme by default
* Adding a patch to have fluxbox use x-terminal-emulator
  over xterm. Closes: #591694 (LP: #580485)
* Adding a patch to allow titlebar-window dragging.
* Changed the flags in rules to pull from a script. This script
  lets us un-hardcode what theme is default. Be sure there
  is a theme pack!
* Added comments to my patches.
* Removing debian/docs, empty file.
* Fixing fluxbox.desktop to remove all the warnings from
  desktop-file-validate
* Fixing libtool issue by running an update before
  configure in the rules script.
* Added a compile flag script to auto-detect what platform
  we are running on, and apply the correct theme. This
  should solve Ubuntnu issues later on.
* adding in a get-orig-source rule
* fixing the upstream version number to pinpoint
  the commit ( thanks, lfaraone ).
* adding a rule for get-orig-source. ( thanks again,
  lfaraone ).
* Updated rules to actually allow us to do a build from it
* Removed Denis from the uploaders ( as per an email
  conversation )
* Removing madduck from the uploaders ( thanks for asking,
  lfaraone. ). Thanks for your hard work, madduck.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Signal.hh for FbTk, Fluxbox Toolkit
 
2
// Copyright (c) 2008 Henrik Kinnunen (fluxgen at fluxbox dot org)
 
3
//
 
4
// Permission is hereby granted, free of charge, to any person obtaining a
 
5
// copy of this software and associated documentation files (the "Software"),
 
6
// to deal in the Software without restriction, including without limitation
 
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
// and/or sell copies of the Software, and to permit persons to whom the
 
9
// Software is furnished to do so, subject to the following conditions:
 
10
//
 
11
// The above copyright notice and this permission notice shall be included in
 
12
// all copies or substantial portions of the Software.
 
13
//
 
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
19
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
20
// DEALINGS IN THE SOFTWARE.
 
21
 
 
22
#ifndef FBTK_SIGNAL_HH
 
23
#define FBTK_SIGNAL_HH
 
24
 
 
25
#include "Slot.hh"
 
26
#include <list>
 
27
#include <map>
 
28
#include <vector>
 
29
#include <set>
 
30
 
 
31
namespace FbTk {
 
32
 
 
33
/// \namespace Implementation details for signals, do not use anything in this namespace
 
34
namespace SigImpl {
 
35
 
 
36
/**
 
37
 * Parent class for all \c Signal[0...*] classes.
 
38
 * It handles the disconnect and holds all the slots. The connect must be
 
39
 * handled by the child class so it can do the type checking.
 
40
 */
 
41
class SignalHolder {
 
42
public:
 
43
    /// Special tracker interface used by SignalTracker.
 
44
    class Tracker {
 
45
    public:
 
46
        virtual ~Tracker() { }
 
47
        /// Disconnect this holder.
 
48
        virtual void disconnect(SignalHolder& signal) = 0;
 
49
    };
 
50
 
 
51
    /// Do not use this type outside this class
 
52
    typedef std::list<SlotHolder> SlotList;
 
53
 
 
54
    typedef SlotList::iterator Iterator;
 
55
    typedef Iterator SlotID;
 
56
    typedef SlotList::const_iterator ConstIterator;
 
57
 
 
58
    ~SignalHolder() {
 
59
        // Disconnect this holder from all trackers.
 
60
        for (Trackers::iterator it = m_trackers.begin(),
 
61
                 it_end = m_trackers.end();
 
62
             it != it_end; ++it ) {
 
63
            (*it)->disconnect(*this);
 
64
        }
 
65
    }
 
66
 
 
67
    /// Remove a specific slot \c id from this signal
 
68
    void disconnect(SlotID slotIt) {
 
69
        m_slots.erase( slotIt );
 
70
    }
 
71
 
 
72
 
 
73
    /// Removes all slots connected to this
 
74
    void clear() {
 
75
        m_slots.clear();
 
76
    }
 
77
 
 
78
    void connectTracker(SignalHolder::Tracker& tracker) {
 
79
        m_trackers.insert(&tracker);
 
80
    }
 
81
 
 
82
    void disconnectTracker(SignalHolder::Tracker& tracker) {
 
83
        m_trackers.erase(&tracker);
 
84
    }
 
85
 
 
86
protected:
 
87
    ConstIterator begin() const { return m_slots.begin(); }
 
88
    ConstIterator end() const { return m_slots.end(); }
 
89
 
 
90
    Iterator begin() { return m_slots.begin(); }
 
91
    Iterator end() { return m_slots.end(); }
 
92
 
 
93
    /// Connect a slot to this signal. Must only be called by child classes.
 
94
    SlotID connect(const SlotHolder& slot) {
 
95
        return m_slots.insert(m_slots.end(), slot);
 
96
    }
 
97
 
 
98
private:
 
99
    typedef std::set<Tracker*> Trackers;
 
100
    SlotList m_slots; ///< all slots connected to a signal
 
101
    Trackers m_trackers; ///< all instances that tracks this signal.
 
102
};
 
103
 
 
104
/// Signal with no argument
 
105
template <typename ReturnType>
 
106
class Signal0: public SignalHolder {
 
107
public:
 
108
    typedef Slot0<ReturnType> SlotType;
 
109
 
 
110
    ~Signal0() { }
 
111
 
 
112
    void emit() {
 
113
        for ( Iterator it = begin(); it != end(); ++it ) {
 
114
            static_cast<SlotType&>(*it)();
 
115
        }
 
116
    }
 
117
 
 
118
    SlotID connect(const SlotType& slot) {
 
119
        return SignalHolder::connect(slot);
 
120
    }
 
121
};
 
122
 
 
123
/// Signal with one argument
 
124
template <typename ReturnType, typename Arg1>
 
125
class Signal1: public SignalHolder {
 
126
public:
 
127
    typedef Slot1<ReturnType, Arg1> SlotType;
 
128
 
 
129
    ~Signal1() { }
 
130
 
 
131
    void emit(Arg1 arg) {
 
132
        for ( Iterator it = begin(); it != end(); ++it ) {
 
133
            static_cast<SlotType&>(*it)(arg);
 
134
        }
 
135
    }
 
136
 
 
137
    SlotID connect(const SlotType& slot) {
 
138
        return SignalHolder::connect(slot);
 
139
    }
 
140
 
 
141
};
 
142
 
 
143
/// Signal with two arguments
 
144
template <typename ReturnType, typename Arg1, typename Arg2>
 
145
class Signal2: public SignalHolder {
 
146
public:
 
147
    typedef Slot2<ReturnType, Arg1, Arg2> SlotType;
 
148
 
 
149
    ~Signal2() { }
 
150
 
 
151
    void emit(Arg1 arg1, Arg2 arg2) {
 
152
        for ( Iterator it = begin(); it != end(); ++it ) {
 
153
            static_cast<SlotType&>(*it)(arg1, arg2);
 
154
        }
 
155
    }
 
156
 
 
157
    SlotID connect(const SlotType& slot) {
 
158
        return SignalHolder::connect(slot);
 
159
    }
 
160
};
 
161
 
 
162
/// Signal with three arguments
 
163
template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3>
 
164
class Signal3: public SignalHolder {
 
165
public:
 
166
    typedef Slot3<ReturnType, Arg1, Arg2, Arg3> SlotType;
 
167
 
 
168
    ~Signal3() { }
 
169
 
 
170
    void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
 
171
        for ( Iterator it = begin(); it != end(); ++it ) {
 
172
            static_cast<SlotType&>(*it)(arg1, arg2, arg3);
 
173
        }
 
174
    }
 
175
 
 
176
    SlotID connect(const SlotType& slot) {
 
177
        return SignalHolder::connect(slot);
 
178
    }
 
179
 
 
180
};
 
181
 
 
182
struct EmptyArg {};
 
183
 
 
184
} // namespace SigImpl
 
185
 
 
186
 
 
187
/// Specialization for three arguments.
 
188
template <typename ReturnType,
 
189
          typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg >
 
190
class Signal: public SigImpl::Signal3< ReturnType, Arg1, Arg2, Arg3 > {
 
191
public:
 
192
};
 
193
 
 
194
/// Specialization for two arguments.
 
195
template <typename ReturnType, typename Arg1, typename Arg2>
 
196
class Signal<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::Signal2< ReturnType, Arg1, Arg2 > {
 
197
public:
 
198
};
 
199
 
 
200
/// Specialization for one argument.
 
201
template <typename ReturnType, typename Arg1>
 
202
class Signal<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::Signal1< ReturnType, Arg1 > {
 
203
public:
 
204
};
 
205
 
 
206
/// Specialization for no argument.
 
207
template <typename ReturnType>
 
208
class Signal<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::Signal0< ReturnType > {
 
209
public:
 
210
};
 
211
 
 
212
/**
 
213
 * Tracks a signal during it's life time. All signals connected using \c
 
214
 * SignalTracker::join will be erased when this instance dies.
 
215
 */
 
216
class SignalTracker: public SigImpl::SignalHolder::Tracker {
 
217
public:
 
218
    /// Internal type, do not use.
 
219
    typedef std::map<SigImpl::SignalHolder*,
 
220
                     SigImpl::SignalHolder::SlotID> Connections;
 
221
    typedef Connections::iterator TrackID; ///< \c ID type for join/leave.
 
222
 
 
223
    ~SignalTracker() {
 
224
        leaveAll();
 
225
    }
 
226
 
 
227
    /// Starts tracking a signal.
 
228
    /// @return A tracking ID
 
229
    template <typename Signal, typename Functor>
 
230
    TrackID join(Signal& sig, const Functor& functor) {
 
231
        ValueType value = ValueType(&sig, sig.connect(functor));
 
232
        std::pair<TrackID, bool> ret = m_connections.insert(value);
 
233
        if ( !ret.second ) {
 
234
            // failed to insert this functor
 
235
            sig.disconnect(value.second);
 
236
        }
 
237
 
 
238
        sig.connectTracker(*this);
 
239
 
 
240
        return ret.first;
 
241
    }
 
242
 
 
243
    /// Leave tracking for a signal
 
244
    /// @param id the \c id from the previous \c join 
 
245
   void leave(TrackID id, bool withTracker = false) {
 
246
       // keep temporary, while disconnecting we can
 
247
       // in some strange cases get a call to this again
 
248
        ValueType tmp = *id;
 
249
        m_connections.erase(id);
 
250
        tmp.first->disconnect(tmp.second);
 
251
        if (withTracker)
 
252
            tmp.first->disconnectTracker(*this);
 
253
    }
 
254
 
 
255
    /// Leave tracking for a signal
 
256
    /// @param sig the signal to leave
 
257
    template <typename Signal>
 
258
    void leave(Signal &sig) {
 
259
        Iterator it = m_connections.find(&sig);
 
260
        if (it != m_connections.end()) {
 
261
            leave(it);
 
262
        }
 
263
    }
 
264
 
 
265
 
 
266
    void leaveAll() {
 
267
        // disconnect all connections
 
268
        for ( ; !m_connections.empty(); ) {
 
269
            leave(m_connections.begin(), true);
 
270
        }
 
271
    }
 
272
 
 
273
protected:
 
274
 
 
275
    virtual void disconnect(SigImpl::SignalHolder& signal) {
 
276
        m_connections.erase(&signal);
 
277
    }
 
278
 
 
279
private:
 
280
    typedef Connections::value_type ValueType;
 
281
    typedef Connections::iterator Iterator;
 
282
    /// holds all connections to different signals and slots.
 
283
    Connections m_connections;
 
284
};
 
285
 
 
286
 
 
287
} // namespace FbTk
 
288
 
 
289
#endif // FBTK_SIGNAL_HH