Using mutexes around accesses to refcounts seems to make the Windows build much less...
[synfig.git] / synfig-core / trunk / src / synfig / node.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file node.h
3 **      \brief Template Header
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === S T A R T =========================================================== */
25
26 #ifndef __SYNFIG_PARENTNODE_H
27 #define __SYNFIG_PARENTNODE_H
28
29 /* === H E A D E R S ======================================================= */
30
31 #include <sigc++/signal.h>
32 #include <set>
33 #include "time.h"
34 #include "guid.h"
35 #include <ETL/handle>
36 #include "interpolation.h"
37 #include "mutex.h"
38
39 /* === M A C R O S ========================================================= */
40
41 // When a PasteCanvas layer has a non-zero 'time offset' parameter, should
42 // the waypoints shown for the canvas be adjusted?  This currently only
43 // partially works - see the TODO at the end of layer_pastecanvas.cpp
44 #define ADJUST_WAYPOINTS_FOR_TIME_OFFSET
45
46 /* === T Y P E D E F S ===================================================== */
47
48 /* === C L A S S E S & S T R U C T S ======================================= */
49
50 namespace synfig {
51
52 class TimePoint
53 {
54         GUID guid;
55         Time time;
56         Interpolation before,after;
57 public:
58
59         TimePoint(const Time& x=Time::begin()):
60                 guid(0),
61                 time(x),
62                 before(INTERPOLATION_NIL),
63                 after(INTERPOLATION_NIL)
64         {
65         }
66
67 #ifdef _DEBUG
68         const char *c_str()const;
69 #endif
70
71         const GUID& get_guid()const { return guid; }
72         const Time& get_time()const { return time; }
73         Interpolation get_before()const { return before; }
74         Interpolation get_after()const { return after; }
75
76         void set_guid(const GUID& x) { guid=x; }
77         void set_time(const Time& x) { time=x; }
78         void set_before(Interpolation x) { before=x; }
79         void set_after(Interpolation x) { after=x; }
80
81         void absorb(const TimePoint& x);
82 }; // END of class TimePoint
83
84 inline TimePoint operator+(TimePoint lhs,const Time& rhs)
85         { lhs.set_time(lhs.get_time()+rhs); return lhs; }
86
87 inline TimePoint operator-(TimePoint lhs,const Time& rhs)
88         { lhs.set_time(lhs.get_time()-rhs); return lhs; }
89
90 inline bool operator<(const TimePoint& lhs,const TimePoint& rhs)
91         { return lhs.get_time()<rhs.get_time(); }
92
93 inline bool operator<(const TimePoint& lhs,const Time& rhs)
94         { return lhs.get_time()<rhs; }
95
96 inline bool operator<(const Time& lhs,const TimePoint& rhs)
97         { return lhs<rhs.get_time(); }
98
99 inline bool operator==(const TimePoint& lhs,const TimePoint& rhs)
100         { return lhs.get_time()==rhs.get_time(); }
101
102 inline bool operator!=(const TimePoint& lhs,const TimePoint& rhs)
103         { return lhs.get_time()!=rhs.get_time(); }
104
105 class TimePointSet : public std::set<TimePoint>
106 {
107 public:
108         iterator insert(const TimePoint& x);
109
110         template <typename ITER> void insert(ITER begin, ITER end)
111                 { for(;begin!=end;++begin) insert(*begin); }
112
113 }; // END of class TimePointSet
114
115 class Node : public etl::rshared_object
116 {
117         /*
118  --     ** -- T Y P E S -----------------------------------------------------------
119         */
120
121 public:
122
123         //! \writeme
124         typedef TimePointSet    time_set;
125
126         /*
127  --     ** -- D A T A -------------------------------------------------------------
128         */
129
130 private:
131
132         //! \writeme
133         GUID guid_;
134
135         //! cached time values for all the children
136         mutable time_set        times;
137
138         //! \writeme
139         mutable bool            bchanged;
140
141         //! \writeme
142         mutable int time_last_changed_;
143
144         //! \writeme
145         mutable RWLock rw_lock_;
146
147         //! \writeme
148         bool deleting_;
149
150 public:
151
152         //! \todo This should really be private
153         std::set<Node*>         parent_set;
154
155         /*
156  -- ** -- S I G N A L S -------------------------------------------------------
157         */
158
159 private:
160
161         sigc::signal<void> signal_changed_;
162
163         //!     GUID Changed
164         /*! \note The second parameter is the *OLD* guid! */
165         sigc::signal<void,GUID> signal_guid_changed_;
166
167         //!     Deleted
168         sigc::signal<void> signal_deleted_;
169
170         /*
171  -- ** -- S I G N A L   I N T E R F A C E -------------------------------------
172         */
173
174 public:
175
176         sigc::signal<void>& signal_deleted() { return signal_deleted_; }
177
178         sigc::signal<void>& signal_changed() { return signal_changed_; }
179
180         //!     GUID Changed
181         /*! \note The second parameter is the *OLD* guid! */
182         sigc::signal<void,GUID>& signal_guid_changed() { return signal_guid_changed_; }
183
184         /*
185  --     ** -- C O N S T R U C T O R S ---------------------------------------------
186         */
187
188 protected:
189
190         Node();
191
192         // This class cannot be copied -- use clone() if necessary
193 private:
194         Node(const Node &x);
195
196 public:
197         virtual ~Node();
198
199         /*
200  --     ** -- M E M B E R   F U N C T I O N S -------------------------------------
201         */
202
203 public:
204
205         void changed();
206
207         //! Gets the GUID for this value node
208         const GUID& get_guid()const;
209
210         //! Sets the GUID for this value node
211         void set_guid(const GUID& x);
212
213         int get_time_last_changed()const;
214
215         void add_child(Node*x);
216
217         void remove_child(Node*x);
218
219         int parent_count()const;
220
221         const time_set &get_times() const;
222
223         RWLock& get_rw_lock()const { return rw_lock_; }
224
225 protected:
226
227         void begin_delete();
228
229         /*
230  --     ** -- V I R T U A L   F U N C T I O N S -----------------------------------
231         */
232
233 protected:
234         virtual void on_changed();
235
236         virtual void on_guid_changed(GUID guid);
237
238         /*!     Function to be overloaded that fills
239         */
240         virtual void get_times_vfunc(time_set &set) const = 0;
241 };
242
243 synfig::Node* find_node(const synfig::GUID& guid);
244
245 template<typename T> etl::handle<T>
246 guid_cast(const synfig::GUID& guid)
247 {
248         return etl::handle<T>::cast_dynamic(synfig::find_node(guid));
249 }
250
251 #ifdef _DEBUG
252 template <typename T>
253 synfig::String set_string(T start, T end)
254 {
255         synfig::String ret("[");
256         bool started = false;
257
258         while (start != end)
259         {
260                 if (started)    ret += ", ";
261                 else                    started = true;
262
263                 ret += synfig::String((*start).c_str());
264                 start++;
265         }
266
267         return ret + "]";
268 }
269
270 template <typename T>
271 synfig::String set_string(T set)
272 {
273         return set_string(set.begin(), set.end());
274 }
275 #endif // _DEBUG
276
277 typedef etl::handle<Node> NodeHandle;
278
279 }; // END of namespace synfig
280
281 /* === E N D =============================================================== */
282
283 #endif