Fixed some more confidential notices
[synfig.git] / synfig-core / tags / stable / src / sinfg / node.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file node.cpp
3 **      \brief Template File
4 **
5 **      $Id: node.cpp,v 1.5 2005/01/07 03:29:12 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #define HASH_MAP_H <ext/hash_map>
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "node.h"
34
35 #ifdef HASH_MAP_H
36 #include HASH_MAP_H
37 using namespace __gnu_cxx;
38 #else
39 #include <map>
40 #endif
41
42 #endif
43
44 /* === U S I N G =========================================================== */
45
46 using namespace std;
47 using namespace etl;
48 using namespace sinfg;
49
50 /* === M A C R O S ========================================================= */
51
52 // About BE_FRUGAL_WITH_GUIDS
53 // If this macro is set, then a GUID will NOT
54 // be calculated until the first call to get_guid()
55 // This also means that the node doesn't get
56 // added to the database until get_guid() is called
57 // for the first time, or set_guid() is called.
58 // If it is expensive to calculate GUIDs, then
59 // this can improve performance a tad in
60 // some cases. Otherwise, it doesn't change
61 // much of anything.
62 #define BE_FRUGAL_WITH_GUIDS 1
63
64 #ifndef __sys_clock
65 #ifndef _WIN32
66 # include <time.h>
67 # define __sys_clock    ::clock
68 #else
69 # ifdef __GNUG__
70 #  include <time.h>
71 #  define __sys_clock   ::clock
72 # else
73 typedef int clock_t;
74 extern clock_t _clock();
75 #  define CLOCKS_PER_SEC 1000
76 #  define __sys_clock   _clock
77 # endif
78 #endif
79 #endif
80
81 /* === G L O B A L S ======================================================= */
82
83 #ifdef HASH_MAP_H
84 typedef hash_map<GUID,Node*,GUIDHash> GlobalNodeMap;
85 #else
86 typedef map<GUID,Node*> GlobalNodeMap;
87 #endif
88
89 static GlobalNodeMap* global_node_map_;
90
91 static GlobalNodeMap& global_node_map()
92 {
93         if(!global_node_map_)
94                 global_node_map_=new GlobalNodeMap;
95         return *global_node_map_;
96 }
97
98 /* === P R O C E D U R E S ================================================= */
99
100 sinfg::Node*
101 sinfg::find_node(const GUID& guid)
102 {
103         if(global_node_map().count(guid)==0)
104                 return 0;
105         return global_node_map()[guid];
106 }
107
108 static void
109 refresh_node(sinfg::Node* node, GUID old_guid)
110 {
111         assert(global_node_map().count(old_guid));
112         global_node_map().erase(old_guid);
113         assert(!global_node_map().count(old_guid));
114         global_node_map()[node->get_guid()]=node;
115 }
116
117 /* === M E T H O D S ======================================================= */
118
119 void
120 TimePoint::absorb(const TimePoint& x)
121 {
122         if(get_guid()==x.get_guid())
123                 return;
124         set_guid(get_guid()^x.get_guid());
125         
126         if(get_after()==INTERPOLATION_NIL)
127                 set_after(x.get_after());
128         if(get_before()==INTERPOLATION_NIL)
129                 set_before(x.get_before());
130         
131         if(get_after()!=x.get_after() && x.get_after()!=INTERPOLATION_NIL)
132                 set_after(INTERPOLATION_UNDEFINED);
133         if(get_before()!=x.get_before() && x.get_before()!=INTERPOLATION_NIL)
134                 set_before(INTERPOLATION_UNDEFINED);    
135 }
136
137 TimePointSet::iterator
138 TimePointSet::insert(const TimePoint& x)
139 {
140         iterator iter(find(x));
141         if(iter!=end())
142         {
143                 const_cast<TimePoint&>(*iter).absorb(x);
144                 return iter;
145         }
146         return std::set<TimePoint>::insert(x).first;
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 Node::Node():
164         guid_(0),
165         bchanged(true),
166         deleting_(false)
167 {
168 #ifndef BE_FRUGAL_WITH_GUIDS
169         guid_.make_unique();
170         assert(guid_);
171         assert(!global_node_map().count(guid_));
172         global_node_map()[guid_]=this;  
173 #endif
174 }
175
176 Node::~Node()
177 {
178         begin_delete();
179
180         if(guid_)
181         {
182                 assert(global_node_map().count(guid_));
183                 global_node_map().erase(guid_);
184                 assert(!global_node_map().count(guid_));
185         }
186 }
187
188 void
189 Node::changed()
190 {
191         time_last_changed_=__sys_clock();
192         on_changed();
193 }
194
195
196 //! Gets the GUID for this value node
197 const GUID&
198 Node::get_guid()const
199 {
200 #ifdef BE_FRUGAL_WITH_GUIDS
201         if(!guid_)
202         {
203                 guid_.make_unique();
204                 assert(guid_);
205                 assert(!global_node_map().count(guid_));
206                 global_node_map()[guid_]=this;  
207         }
208 #endif
209         
210         return guid_;
211 }
212
213 //! Sets the GUID for this value node
214 void
215 Node::set_guid(const GUID& x)
216 {
217         assert(x);
218
219 #ifdef BE_FRUGAL_WITH_GUIDS
220         if(!guid_)
221         {
222                 guid_=x;
223                 assert(!global_node_map().count(guid_));
224                 global_node_map()[guid_]=this;  
225         }
226         else
227 #endif
228         if(guid_!=x)
229         {
230                 GUID oldguid(guid_);
231                 guid_=x;
232                 refresh_node(this, oldguid);
233                 on_guid_changed(oldguid);
234         }
235 }
236
237 int
238 Node::get_time_last_changed()const
239 {
240         return time_last_changed_;
241 }
242
243 void
244 Node::add_child(Node*x)
245 {
246         x->parent_set.insert(this);
247 }
248
249 void
250 Node::remove_child(Node*x)
251 {
252         if(x->parent_set.count(this)) x->parent_set.erase(this);
253 }
254
255 int
256 Node::parent_count()const
257 {
258         return parent_set.size();
259 }
260
261 const Node::time_set &
262 Node::get_times() const
263 {
264         if(bchanged)
265         {
266                 times.clear();
267                 get_times_vfunc(times);
268                 bchanged = false;
269         }
270         
271         //set the output set...
272         return times;
273 }
274
275 void
276 Node::begin_delete()
277 {
278         if(!deleting_)
279         {
280                 deleting_=true; signal_deleted()();
281         }
282 }
283
284 void
285 Node::on_changed()
286 {
287         bchanged = true;
288         signal_changed()();
289
290         std::set<Node*>::iterator iter;
291         for(iter=parent_set.begin();iter!=parent_set.end();++iter)
292         {
293                 (*iter)->changed();
294         }
295 }
296
297 void
298 Node::on_guid_changed(GUID guid)
299 {
300         signal_guid_changed()(guid);
301 }