2009-10-09 Chris Toshok <toshok@ximian.com>
[moon.git] / src / resources.cpp
blobc83e64f4ae354bf62ff80e7c1c7d4fadab0e9d32
1 /*
2 * resources.cpp
4 * Copyright 2007 Novell, Inc. (http://www.novell.com)
6 * See the LICENSE file included with the distribution for details.
7 *
8 */
10 #include <config.h>
11 #include <stdlib.h>
13 #include "runtime.h"
14 #include "resources.h"
15 #include "namescope.h"
16 #include "error.h"
18 static void
19 free_value (Value *value)
21 delete value;
24 ResourceDictionary::ResourceDictionary ()
26 SetObjectType (Type::RESOURCE_DICTIONARY);
27 hash = g_hash_table_new_full (g_str_hash,
28 g_str_equal,
29 (GDestroyNotify)g_free,
30 (GDestroyNotify)free_value);
31 from_resource_dictionary_api = false;
34 ResourceDictionary::~ResourceDictionary ()
36 g_hash_table_destroy (hash);
39 bool
40 ResourceDictionary::CanAdd (Value *value)
42 return true;
45 bool
46 ResourceDictionary::Add (const char* key, Value *value)
48 MoonError err;
49 return AddWithError (key, value, &err);
52 bool
53 ResourceDictionary::AddWithError (const char* key, Value *value, MoonError *error)
55 if (!key) {
56 MoonError::FillIn (error, MoonError::ARGUMENT_NULL, "key was null");
57 return false;
60 if (ContainsKey (key)) {
61 MoonError::FillIn (error, MoonError::ARGUMENT, "An item with the same key has already been added");
62 return false;
65 Value *v = new Value (*value);
67 from_resource_dictionary_api = true;
68 bool result = Collection::AddWithError (v, error) != -1;
69 from_resource_dictionary_api = false;
70 if (result)
71 g_hash_table_insert (hash, g_strdup (key), v);
72 return result;
75 bool
76 ResourceDictionary::Clear ()
78 #if GLIB_CHECK_VERSION(2,12,0)
79 if (glib_check_version (2,12,0))
80 g_hash_table_remove_all (hash);
81 else
82 #endif
83 g_hash_table_foreach_remove (hash, (GHRFunc) gtk_true, NULL);
85 from_resource_dictionary_api = true;
86 bool rv = Collection::Clear ();
87 from_resource_dictionary_api = false;
89 return rv;
92 bool
93 ResourceDictionary::ContainsKey (const char *key)
95 if (!key)
96 return false;
98 gpointer orig_value;
99 gpointer orig_key;
101 return g_hash_table_lookup_extended (hash, key,
102 &orig_key, &orig_value);
105 bool
106 ResourceDictionary::Remove (const char *key)
108 if (!key)
109 return false;
111 /* check if the item exists first */
112 Value* orig_value;
113 gpointer orig_key;
115 if (!g_hash_table_lookup_extended (hash, key,
116 &orig_key, (gpointer*)&orig_value))
117 return false;
119 from_resource_dictionary_api = true;
120 Collection::Remove (orig_value);
121 from_resource_dictionary_api = false;
123 g_hash_table_remove (hash, key);
125 return true;
128 bool
129 ResourceDictionary::Set (const char *key, Value *value)
131 /* check if the item exists first */
132 Value* orig_value;
133 gpointer orig_key;
135 if (g_hash_table_lookup_extended (hash, key,
136 &orig_key, (gpointer*)&orig_value)) {
137 return false;
140 Value *v = new Value (*value);
142 from_resource_dictionary_api = true;
143 Collection::Remove (orig_value);
144 Collection::Add (v);
145 from_resource_dictionary_api = false;
147 g_hash_table_replace (hash, g_strdup (key), v);
149 return true; // XXX
152 Value*
153 ResourceDictionary::Get (const char *key, bool *exists)
155 Value *v = NULL;
156 gpointer orig_key;
158 *exists = g_hash_table_lookup_extended (hash, key,
159 &orig_key, (gpointer*)&v);
161 if (!*exists)
162 v = GetFromMergedDictionaries (key, exists);
164 return v;
167 Value *
168 ResourceDictionary::GetFromMergedDictionaries (const char *key, bool *exists)
170 Value *v = NULL;
172 ResourceDictionaryCollection *merged = GetMergedDictionaries ();
174 if (!merged) {
175 *exists = false;
176 return NULL;
179 CollectionIterator *iter = merged->GetIterator ();
180 while (iter->Next () && !*exists) {
181 int error;
182 Value *dict_v = iter->GetCurrent (&error);
184 if (error)
185 continue;
187 ResourceDictionary *dict = dict_v->AsResourceDictionary ();
188 v = dict->Get (key, exists);
191 return v;
194 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
195 bool
196 ResourceDictionary::AddedToCollection (Value *value, MoonError *error)
198 if (value->Is(Type::DEPENDENCY_OBJECT)) {
199 DependencyObject *obj = value->AsDependencyObject ();
200 DependencyObject *parent = obj ? obj->GetParent () : NULL;
201 // Call SetSurface() /before/ setting the logical parent
202 // because Storyboard::SetSurface() needs to be able to
203 // distinguish between the two cases.
205 if (parent) {
206 MoonError::FillIn (error, MoonError::INVALID_OPERATION, "Element is already a child of another element.");
207 return false;
210 obj->SetSurface (GetSurface ());
211 obj->SetParent (this, error);
212 if (error->number)
213 return false;
215 obj->AddPropertyChangeListener (this);
217 if (!from_resource_dictionary_api) {
218 const char *key = obj->GetName();
220 if (!key) {
221 MoonError::FillIn (error, MoonError::ARGUMENT_NULL, "key was null");
222 return false;
225 if (ContainsKey (key)) {
226 MoonError::FillIn (error, MoonError::ARGUMENT, "An item with the same key has already been added");
227 return false;
232 bool rv = Collection::AddedToCollection (value, error);
234 if (rv && !from_resource_dictionary_api && value->Is(Type::DEPENDENCY_OBJECT)) {
235 DependencyObject *obj = value->AsDependencyObject ();
236 const char *key = obj->GetName();
238 g_hash_table_insert (hash, g_strdup (key), new Value (obj));
241 return rv;
244 static gboolean
245 remove_from_hash_by_value (gpointer key,
246 gpointer value,
247 gpointer user_data)
249 Value *v = (Value*)value;
251 return (v->Is (Type::DEPENDENCY_OBJECT) && v->AsDependencyObject() == user_data);
254 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
255 void
256 ResourceDictionary::RemovedFromCollection (Value *value)
258 if (value->Is (Type::DEPENDENCY_OBJECT)) {
259 DependencyObject *obj = value->AsDependencyObject ();
261 obj->RemovePropertyChangeListener (this);
262 obj->SetParent (NULL, NULL);
263 obj->SetSurface (NULL);
265 Collection::RemovedFromCollection (value);
267 if (!from_resource_dictionary_api)
268 g_hash_table_foreach_remove (hash, remove_from_hash_by_value, value->AsDependencyObject ());
272 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
273 void
274 ResourceDictionary::SetSurface (Surface *surface)
276 if (GetSurface() == surface)
277 return;
279 Value *value;
281 for (guint i = 0; i < array->len; i++) {
282 value = (Value *) array->pdata[i];
283 if (value->Is (Type::DEPENDENCY_OBJECT)) {
284 DependencyObject *obj = value->AsDependencyObject ();
285 obj->SetSurface (surface);
289 Collection::SetSurface (surface);
292 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
293 void
294 ResourceDictionary::UnregisterAllNamesRootedAt (NameScope *from_ns)
296 Value *value;
298 for (guint i = 0; i < array->len; i++) {
299 value = (Value *) array->pdata[i];
300 if (value->Is (Type::DEPENDENCY_OBJECT)) {
301 DependencyObject *obj = value->AsDependencyObject ();
302 obj->UnregisterAllNamesRootedAt (from_ns);
306 Collection::UnregisterAllNamesRootedAt (from_ns);
309 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
310 void
311 ResourceDictionary::RegisterAllNamesRootedAt (NameScope *to_ns, MoonError *error)
313 Value *value;
315 for (guint i = 0; i < array->len; i++) {
316 if (error->number)
317 break;
319 value = (Value *) array->pdata[i];
320 if (value->Is (Type::DEPENDENCY_OBJECT)) {
321 DependencyObject *obj = value->AsDependencyObject ();
322 obj->RegisterAllNamesRootedAt (to_ns, error);
326 Collection::RegisterAllNamesRootedAt (to_ns, error);