4 * Copyright 2007 Novell, Inc. (http://www.novell.com)
6 * See the LICENSE file included with the distribution for details.
14 #include "resources.h"
15 #include "namescope.h"
19 free_value (Value
*value
)
24 ResourceDictionary::ResourceDictionary ()
26 SetObjectType (Type::RESOURCE_DICTIONARY
);
27 hash
= g_hash_table_new_full (g_str_hash
,
29 (GDestroyNotify
)g_free
,
30 (GDestroyNotify
)free_value
);
31 from_resource_dictionary_api
= false;
34 ResourceDictionary::~ResourceDictionary ()
36 g_hash_table_destroy (hash
);
40 ResourceDictionary::CanAdd (Value
*value
)
46 ResourceDictionary::Add (const char* key
, Value
*value
)
49 return AddWithError (key
, value
, &err
);
53 ResourceDictionary::AddWithError (const char* key
, Value
*value
, MoonError
*error
)
56 MoonError::FillIn (error
, MoonError::ARGUMENT_NULL
, "key was null");
60 if (ContainsKey (key
)) {
61 MoonError::FillIn (error
, MoonError::ARGUMENT
, "An item with the same key has already been added");
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;
71 g_hash_table_insert (hash
, g_strdup (key
), v
);
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
);
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;
93 ResourceDictionary::ContainsKey (const char *key
)
101 return g_hash_table_lookup_extended (hash
, key
,
102 &orig_key
, &orig_value
);
106 ResourceDictionary::Remove (const char *key
)
111 /* check if the item exists first */
115 if (!g_hash_table_lookup_extended (hash
, key
,
116 &orig_key
, (gpointer
*)&orig_value
))
119 from_resource_dictionary_api
= true;
120 Collection::Remove (orig_value
);
121 from_resource_dictionary_api
= false;
123 g_hash_table_remove (hash
, key
);
129 ResourceDictionary::Set (const char *key
, Value
*value
)
131 /* check if the item exists first */
135 if (g_hash_table_lookup_extended (hash
, key
,
136 &orig_key
, (gpointer
*)&orig_value
)) {
140 Value
*v
= new Value (*value
);
142 from_resource_dictionary_api
= true;
143 Collection::Remove (orig_value
);
145 from_resource_dictionary_api
= false;
147 g_hash_table_replace (hash
, g_strdup (key
), v
);
153 ResourceDictionary::Get (const char *key
, bool *exists
)
158 *exists
= g_hash_table_lookup_extended (hash
, key
,
159 &orig_key
, (gpointer
*)&v
);
162 v
= GetFromMergedDictionaries (key
, exists
);
168 ResourceDictionary::GetFromMergedDictionaries (const char *key
, bool *exists
)
172 ResourceDictionaryCollection
*merged
= GetMergedDictionaries ();
179 CollectionIterator
*iter
= merged
->GetIterator ();
180 while (iter
->Next () && !*exists
) {
182 Value
*dict_v
= iter
->GetCurrent (&error
);
187 ResourceDictionary
*dict
= dict_v
->AsResourceDictionary ();
188 v
= dict
->Get (key
, exists
);
194 // XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
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.
206 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Element is already a child of another element.");
210 obj
->SetSurface (GetSurface ());
211 obj
->SetParent (this, error
);
215 obj
->AddPropertyChangeListener (this);
217 if (!from_resource_dictionary_api
) {
218 const char *key
= obj
->GetName();
221 MoonError::FillIn (error
, MoonError::ARGUMENT_NULL
, "key was null");
225 if (ContainsKey (key
)) {
226 MoonError::FillIn (error
, MoonError::ARGUMENT
, "An item with the same key has already been added");
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
));
245 remove_from_hash_by_value (gpointer key
,
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
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
274 ResourceDictionary::SetSurface (Surface
*surface
)
276 if (GetSurface() == surface
)
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
294 ResourceDictionary::UnregisterAllNamesRootedAt (NameScope
*from_ns
)
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
311 ResourceDictionary::RegisterAllNamesRootedAt (NameScope
*to_ns
, MoonError
*error
)
315 for (guint i
= 0; i
< array
->len
; i
++) {
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
);