Using mutexes around accesses to refcounts seems to make the Windows build much less...
[synfig.git] / synfig-core / trunk / src / synfig / valuenode.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file valuenode.h
3 **      \brief Header file for implementation of the "Placeholder" valuenode conversion.
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 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_VALUENODE_H
27 #define __SYNFIG_VALUENODE_H
28
29 /* === H E A D E R S ======================================================= */
30
31 #include "vector.h"
32 #include "value.h"
33 #include "string.h"
34 #include "releases.h"
35 #include <ETL/handle>
36 #include <ETL/stringf>
37 #include "exception.h"
38 #include <map>
39 #include <sigc++/signal.h>
40 #include "guid.h"
41
42 #ifndef SYNFIG_NO_ANGLE
43 #include <ETL/angle>
44 #endif
45
46 #include "node.h"
47
48 #include <set>
49
50 /* === M A C R O S ========================================================= */
51
52 // This is a hack for GCC 3.0.4... which has a broken dynamic_cast<>
53 // It is deprecated, and will be removed soon.
54 #if ( __GNUC__ == 3 ) && ( __GNUC__MINOR__ == 0 )
55 # define DCAST_HACK_BASECLASS() int cast__
56 # define DCAST_HACK_ID(x)               static const int my_cast__(void) { return x; }
57 # define DCAST_HACK_ENABLE()    cast__=my_cast__()
58 #else
59 # define DCAST_HACK_BASECLASS()
60 # define DCAST_HACK_ID(x)
61 # define DCAST_HACK_ENABLE()
62 #endif
63
64 #define CHECK_TYPE_AND_SET_VALUE(variable, type)                                                \
65         /* I don't think this ever happens - maybe remove this code? */         \
66         if (get_type() == ValueBase::TYPE_NIL) {                                                        \
67                 warning("%s:%d get_type() IS nil sometimes!",                                   \
68                                 __FILE__, __LINE__);                                                                    \
69                 return false;                                                                                                   \
70         }                                                                                                                                       \
71         if (get_type() != ValueBase::TYPE_NIL &&                                                        \
72                 !(ValueBase::same_type_as(value->get_type(), type)) &&                  \
73                 !PlaceholderValueNode::Handle::cast_dynamic(value)) {                   \
74                 error(_("%s:%d wrong type for %s: need %s but got %s"),                 \
75                           __FILE__, __LINE__,                                                                           \
76                           link_local_name(i).c_str(),                                                           \
77                           ValueBase::type_local_name(type).c_str(),                                     \
78                           ValueBase::type_local_name(value->get_type()).c_str());       \
79                 return false;                                                                                                   \
80         }                                                                                                                                       \
81         variable = value;                                                                                                       \
82         signal_child_changed()(i);                                                                                      \
83         signal_value_changed()();                                                                                       \
84         return true
85
86 /* === T Y P E D E F S ===================================================== */
87
88 /* === C L A S S E S & S T R U C T S ======================================= */
89
90 namespace synfig {
91
92 class Canvas;
93 class LinkableValueNode;
94 class Layer;
95
96 /*!     \class ValueNode
97 **      \todo writeme
98 */
99 class ValueNode : public synfig::Node
100 {
101         friend class Layer;
102         friend class LinkableValueNode;
103
104         /*
105  --     ** -- T Y P E S -----------------------------------------------------------
106         */
107
108 public:
109
110         typedef etl::handle<ValueNode> Handle;
111
112         typedef etl::loose_handle<ValueNode> LooseHandle;
113
114         typedef etl::handle<const ValueNode> ConstHandle;
115
116         typedef etl::rhandle<ValueNode> RHandle;
117
118
119         static bool subsys_init();
120
121         static bool subsys_stop();
122
123         /*
124  --     ** -- D A T A -------------------------------------------------------------
125         */
126
127 private:
128         ValueBase::Type type;
129         String name;
130         etl::loose_handle<Canvas> canvas_;
131         etl::loose_handle<Canvas> root_canvas_;
132
133         /*
134  -- ** -- S I G N A L S -------------------------------------------------------
135         */
136
137 private:
138
139         //!     ValueBase Changed
140         sigc::signal<void> signal_value_changed_;
141
142         //!     Children Reordered
143         sigc::signal<void,int*> signal_children_reordered_;
144
145         //!     Child Changed
146         sigc::signal<void,int> signal_child_changed_;
147
148         //!     Child Removed
149         sigc::signal<void,int> signal_child_removed_;
150
151         //!     Child Inserted
152         sigc::signal<void,int> signal_child_inserted_;
153
154         //!     ID Changed
155         sigc::signal<void> signal_id_changed_;
156
157         /*
158  -- ** -- S I G N A L   I N T E R F A C E -------------------------------------
159         */
160
161 public:
162
163         //!     ValueBase Changed
164         sigc::signal<void>& signal_value_changed() { return signal_value_changed_; }
165
166         //!     Children Reordered
167         sigc::signal<void,int*>& signal_children_reordered() { return signal_children_reordered_; }
168
169         //!     Child Changed
170         sigc::signal<void,int>& signal_child_changed() { return signal_child_changed_; }
171
172         //!     Child Removed
173         sigc::signal<void,int>& signal_child_removed() { return signal_child_removed_; }
174
175         //!     Child Inserted
176         sigc::signal<void,int>& signal_child_inserted() { return signal_child_inserted_; }
177
178         //!     ID Changed
179         sigc::signal<void>& signal_id_changed() { return signal_id_changed_; }
180
181         /*
182  --     ** -- C O N S T R U C T O R S ---------------------------------------------
183         */
184
185 protected:
186
187         ValueNode(ValueBase::Type type=ValueBase::TYPE_NIL);
188
189 public:
190
191         virtual ~ValueNode();
192
193         /*
194  --     ** -- M E M B E R   F U N C T I O N S -------------------------------------
195         */
196
197 public:
198
199         //! Returns the value of the ValueNode at time \a t
200         virtual ValueBase operator()(Time /*t*/)const
201                 { return ValueBase(); }
202
203         //! \internal Sets the id of the ValueNode
204         void set_id(const String &x);
205
206         //! Returns the id of the ValueNode
207         /*!     The ID is used for keeping track of a
208         **      specific instance of a ValueNode. */
209         const String &get_id()const { return name; }
210
211         //! Returns the name of the ValueNode type
212         virtual String get_name()const=0;
213
214         //! Returns the localized name of the ValueNode type
215         virtual String get_local_name()const=0;
216
217         //! Return a full description of the ValueNode and its parentage
218         virtual String get_description(bool show_exported_name = true)const;
219
220
221         //! \writeme
222         virtual ValueNode* clone(const GUID& deriv_guid=GUID())const=0;
223
224         //! \writeme
225         bool is_exported()const { return !get_id().empty(); }
226
227         //! Returns the type of the ValueNode
228         ValueBase::Type get_type()const { return type; }
229
230         //! Returns a handle to the parent canvas, if it has one.
231         etl::loose_handle<Canvas> get_parent_canvas()const { return canvas_; }
232
233         //! Returns a handle to the parent canvas, if it has one.
234         etl::loose_handle<Canvas> get_root_canvas()const { return root_canvas_; }
235
236         //! \writeme
237         void set_parent_canvas(etl::loose_handle<Canvas> x);
238
239         //! \writeme
240         void set_root_canvas(etl::loose_handle<Canvas> x);
241
242         //! \writeme
243         String get_relative_id(etl::loose_handle<const Canvas> x)const;
244
245         int replace(etl::handle<ValueNode> x);
246
247 protected:
248         //! Sets the type of the ValueNode
249         void set_type(ValueBase::Type t) { type=t; }
250
251         virtual void on_changed();
252
253 public:
254         DCAST_HACK_BASECLASS();
255         DCAST_HACK_ID(0);
256 }; // END of class ValueNode
257
258 /*!     \class PlaceholderValueNode
259 **      \todo writeme
260 */
261 class PlaceholderValueNode : public ValueNode
262 {
263 public:
264         typedef etl::handle<PlaceholderValueNode> Handle;
265         typedef etl::loose_handle<PlaceholderValueNode> LooseHandle;
266         typedef etl::handle<const PlaceholderValueNode> ConstHandle;
267         typedef etl::rhandle<PlaceholderValueNode> RHandle;
268
269 private:
270
271         PlaceholderValueNode(ValueBase::Type type=ValueBase::TYPE_NIL);
272
273 public:
274
275         virtual ValueBase operator()(Time t)const;
276
277         virtual String get_name()const;
278
279         virtual String get_local_name()const;
280
281         virtual ValueNode* clone(const GUID& deriv_guid=GUID())const;
282
283         static Handle create(ValueBase::Type type=ValueBase::TYPE_NIL);
284
285 protected:
286         virtual void get_times_vfunc(Node::time_set &/*set*/) const {}
287 }; // END of class PlaceholderValueNode
288
289
290 /*!     \class LinkableValueNode
291 **      \todo writeme
292 */
293 class LinkableValueNode : public ValueNode
294 {
295         friend class ValueNode;
296 public:
297
298         typedef etl::handle<LinkableValueNode> Handle;
299
300         typedef etl::loose_handle<LinkableValueNode> LooseHandle;
301
302         typedef etl::handle<const LinkableValueNode> ConstHandle;
303
304         typedef etl::rhandle<LinkableValueNode> RHandle;
305
306
307         //! Type that represents a pointer to a ValueNode's constructor
308         typedef LinkableValueNode* (*Factory)(const ValueBase&);
309
310         typedef bool (*CheckType)(ValueBase::Type);
311
312         struct BookEntry
313         {
314                 String local_name;
315                 Factory factory;
316                 CheckType check_type;
317                 ReleaseVersion release_version; // which version of synfig introduced this valuenode type
318         };
319
320         typedef std::map<String,BookEntry> Book;
321
322         static Book& book();
323
324         static Handle create(const String &name, const ValueBase& x);
325
326         static bool check_type(const String &name, ValueBase::Type x);
327
328 public:
329         LinkableValueNode(ValueBase::Type type=ValueBase::TYPE_NIL):
330                 ValueNode(type) { }
331
332 protected:
333         virtual bool set_link_vfunc(int i,ValueNode::Handle x)=0;
334
335         void unlink_all();
336
337 public:
338
339         virtual int link_count()const=0;
340
341         virtual String link_local_name(int i)const=0;
342
343         virtual String link_name(int i)const=0;
344
345         virtual int get_link_index_from_name(const String &name)const=0;
346
347         virtual ValueNode* clone(const GUID& deriv_guid=GUID())const;
348
349         bool set_link(int i,ValueNode::Handle x);
350         bool set_link(const String &name,ValueNode::Handle x) { return set_link(get_link_index_from_name(name),x);      }
351
352         ValueNode::LooseHandle get_link(int i)const;
353         ValueNode::LooseHandle get_link(const String &name)const { return get_link(get_link_index_from_name(name)); }
354
355         String
356         get_description(int index = -1, bool show_exported_name = true)const;
357
358 protected:
359         //! Sets the type of the ValueNode
360         void set_type(ValueBase::Type t) { ValueNode::set_type(t); }
361
362         virtual ValueNode::LooseHandle get_link_vfunc(int i)const=0;
363
364         // Wrapper for new operator, used by clone()
365         virtual LinkableValueNode* create_new()const=0;
366
367         virtual void get_times_vfunc(Node::time_set &set) const;
368 }; // END of class LinkableValueNode
369
370 /*!     \class ValueNodeList
371 **      \brief A searchable value_node list container
372 **      \warning Do not confuse with ValueNode_DynamicList!
373 **      \todo writeme
374 */
375 class ValueNodeList : public std::list<ValueNode::RHandle>
376 {
377         int placeholder_count_;
378 public:
379         ValueNodeList();
380
381         //! Finds the ValueNode in the list with the given \a name
382         /*!     \return If found, returns a handle to the ValueNode.
383         **              Otherwise, returns an empty handle.
384         */
385         ValueNode::Handle find(const String &name);
386
387         //! Finds the ValueNode in the list with the given \a name
388         /*!     \return If found, returns a handle to the ValueNode.
389         **              Otherwise, returns an empty handle.
390         */
391         ValueNode::ConstHandle find(const String &name)const;
392
393         //! Removes the \a value_node from the list
394         bool erase(ValueNode::Handle value_node);
395
396         //! \writeme
397         bool add(ValueNode::Handle value_node);
398
399         //! \writeme
400         bool count(const String &id)const;
401
402         //! Similar to find, but will create a placeholder value_node if it cannot be found.
403         ValueNode::Handle surefind(const String &name);
404
405         //! Removes any value_nodes with reference counts of 1.
406         void audit();
407
408         //! Placeholder Count
409         int placeholder_count()const { return placeholder_count_; }
410 };
411
412 ValueNode::LooseHandle find_value_node(const GUID& guid);
413
414 }; // END of namespace synfig
415
416 /* === E N D =============================================================== */
417
418 #endif