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