1 /***********************************************************************
2 created: 22/2/2004
3 author: Paul D Turner
4
5 purpose: Implements the WindowFactoryManager
6 *************************************************************************/
7 /***************************************************************************
8 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 ***************************************************************************/
29 #include "CEGUI/WindowFactoryManager.h"
30 #include "CEGUI/WindowFactory.h"
31 #include "CEGUI/Exceptions.h"
32 #include <algorithm>
33
34 // Start of CEGUI namespace section
35 namespace CEGUI
36 {
37 /*************************************************************************
38 Static Data Definitions
39 *************************************************************************/
40 // singleton instance pointer
41 template<> WindowFactoryManager* Singleton<WindowFactoryManager>::ms_Singleton = 0;
42 // list of owned WindowFactory object pointers
43 WindowFactoryManager::OwnedWindowFactoryList WindowFactoryManager::d_ownedFactories;
44
45 //----------------------------------------------------------------------------//
WindowFactoryManager(void)46 WindowFactoryManager::WindowFactoryManager(void)
47 {
48 Logger::getSingleton().logEvent(
49 "CEGUI::WindowFactoryManager singleton created");
50
51 // complete addition of any pre-added WindowFactory objects
52 WindowFactoryManager::OwnedWindowFactoryList::iterator i =
53 d_ownedFactories.begin();
54
55 if (d_ownedFactories.end() != i)
56 {
57 Logger::getSingleton().logEvent(
58 "---- Adding pre-registered WindowFactory objects ----");
59
60 for (; d_ownedFactories.end() != i; ++i)
61 addFactory(*i);
62 }
63 }
64
65 /*************************************************************************
66 Adds a WindowFactory object to the registry
67 *************************************************************************/
addFactory(WindowFactory * factory)68 void WindowFactoryManager::addFactory(WindowFactory* factory)
69 {
70 // throw exception if passed factory is null.
71 if (!factory)
72 {
73 CEGUI_THROW(NullObjectException(
74 "The provided WindowFactory pointer was invalid."));
75 }
76
77 // throw exception if type name for factory is already in use
78 if (d_factoryRegistry.find(factory->getTypeName()) != d_factoryRegistry.end())
79 {
80 CEGUI_THROW(AlreadyExistsException(
81 "A WindowFactory for type '" + factory->getTypeName() +
82 "' is already registered."));
83 }
84
85 // add the factory to the registry
86 d_factoryRegistry[factory->getTypeName()] = factory;
87
88 char addr_buff[32];
89 sprintf(addr_buff, "(%p)", static_cast<void*>(factory));
90 Logger::getSingleton().logEvent("WindowFactory for '" +
91 factory->getTypeName() +"' windows added. " + addr_buff);
92 }
93
94
95 /*************************************************************************
96 removes a WindowFactory from the registry (by name)
97 *************************************************************************/
removeFactory(const String & name)98 void WindowFactoryManager::removeFactory(const String& name)
99 {
100 WindowFactoryRegistry::iterator i = d_factoryRegistry.find(name);
101
102 // exit if no factory exists for this type
103 if (i == d_factoryRegistry.end())
104 return;
105
106 // see if we own this factory
107 OwnedWindowFactoryList::iterator j = std::find(d_ownedFactories.begin(),
108 d_ownedFactories.end(),
109 (*i).second);
110
111 char addr_buff[32];
112 sprintf(addr_buff, "(%p)", static_cast<void*>((*i).second));
113
114 d_factoryRegistry.erase(name);
115
116 Logger::getSingleton().logEvent("WindowFactory for '" + name +
117 "' windows removed. " + addr_buff);
118
119 // delete factory object if we created it
120 if (j != d_ownedFactories.end())
121 {
122 Logger::getSingleton().logEvent("Deleted WindowFactory for '" +
123 (*j)->getTypeName() +
124 "' windows.");
125
126 CEGUI_DELETE_AO (*j);
127 d_ownedFactories.erase(j);
128 }
129 }
130
131
132 /*************************************************************************
133 removes a WindowFactory from the registry (by pointer)
134 *************************************************************************/
removeFactory(WindowFactory * factory)135 void WindowFactoryManager::removeFactory(WindowFactory* factory)
136 {
137 if (factory)
138 {
139 removeFactory(factory->getTypeName());
140 }
141
142 }
143
144 //----------------------------------------------------------------------------//
removeAllFactories(void)145 void WindowFactoryManager::removeAllFactories(void)
146 {
147 while (!d_factoryRegistry.empty())
148 removeFactory((*d_factoryRegistry.begin()).second);
149 }
150
151
152 /*************************************************************************
153 returns a pointer to the requested WindowFactory object
154 *************************************************************************/
getFactory(const String & type) const155 WindowFactory* WindowFactoryManager::getFactory(const String& type) const
156 {
157 // first, dereference aliased types, as needed.
158 String targetType(getDereferencedAliasType(type));
159
160 // try for a 'real' type
161 WindowFactoryRegistry::const_iterator pos = d_factoryRegistry.find(targetType);
162
163 // found an actual factory for this type
164 if (pos != d_factoryRegistry.end())
165 {
166 return pos->second;
167 }
168 // no concrete type, try for a falagard mapped type
169 else
170 {
171 FalagardMapRegistry::const_iterator falagard = d_falagardRegistry.find(targetType);
172
173 // found falagard mapping for this type
174 if (falagard != d_falagardRegistry.end())
175 {
176 // recursively call getFactory on the target base type
177 return getFactory(falagard->second.d_baseType);
178 }
179 // type not found anywhere, give up with an exception.
180 else
181 {
182 CEGUI_THROW(UnknownObjectException(
183 "A WindowFactory object, an alias, or mapping for '" + type +
184 "' Window objects is not registered with the system.\n\n"
185 "Have you forgotten to load a scheme using "
186 "CEGUI::SchemeManager::createFromFile(..)?"));
187 }
188 }
189 }
190
191
192 /*************************************************************************
193 Returns true if a WindowFactory, an alias, or a falagard mapping for
194 a specified window type is present
195 *************************************************************************/
isFactoryPresent(const String & name) const196 bool WindowFactoryManager::isFactoryPresent(const String& name) const
197 {
198 // first, dereference aliased types, as needed.
199 String targetType(getDereferencedAliasType(name));
200
201 // now try for a 'real' type
202 if (d_factoryRegistry.find(targetType) != d_factoryRegistry.end())
203 {
204 return true;
205 }
206 // not a concrete type, so return whether it's a Falagard mapped type.
207 else
208 {
209 return (d_falagardRegistry.find(targetType) != d_falagardRegistry.end());
210 }
211 }
212
213
214 /*************************************************************************
215 Return a WindowFactoryManager::WindowFactoryIterator object to
216 iterate over the available WindowFactory types.
217 *************************************************************************/
getIterator(void) const218 WindowFactoryManager::WindowFactoryIterator WindowFactoryManager::getIterator(void) const
219 {
220 return WindowFactoryIterator(d_factoryRegistry.begin(), d_factoryRegistry.end());
221 }
222
223
224 /*************************************************************************
225 Return a WindowFactoryManager::TypeAliasIterator object to iterate
226 over the defined aliases for window types.
227 *************************************************************************/
getAliasIterator(void) const228 WindowFactoryManager::TypeAliasIterator WindowFactoryManager::getAliasIterator(void) const
229 {
230 return TypeAliasIterator(d_aliasRegistry.begin(), d_aliasRegistry.end());
231 }
232
233
234 /*************************************************************************
235 Add a window type alias mapping
236 *************************************************************************/
addWindowTypeAlias(const String & aliasName,const String & targetType)237 void WindowFactoryManager::addWindowTypeAlias(const String& aliasName, const String& targetType)
238 {
239 TypeAliasRegistry::iterator pos = d_aliasRegistry.find(aliasName);
240
241 if (pos == d_aliasRegistry.end())
242 {
243 d_aliasRegistry[aliasName].d_targetStack.push_back(targetType);
244 }
245 // alias already exists, add our new entry to the list already there
246 else
247 {
248 pos->second.d_targetStack.push_back(targetType);
249 }
250
251 Logger::getSingleton().logEvent("Window type alias named '" + aliasName + "' added for window type '" + targetType +"'.");
252 }
253
254
255 /*************************************************************************
256 Remove a window type alias mapping
257 *************************************************************************/
removeWindowTypeAlias(const String & aliasName,const String & targetType)258 void WindowFactoryManager::removeWindowTypeAlias(const String& aliasName, const String& targetType)
259 {
260 // find alias name
261 TypeAliasRegistry::iterator pos = d_aliasRegistry.find(aliasName);
262
263 // if alias name exists
264 if (pos != d_aliasRegistry.end())
265 {
266 // find the specified target for this alias
267 AliasTargetStack::TargetTypeStack::iterator aliasPos = std::find(pos->second.d_targetStack.begin(), pos->second.d_targetStack.end(), targetType);
268
269 // if the target exists for this alias
270 if (aliasPos != pos->second.d_targetStack.end())
271 {
272 // erase the target mapping
273 pos->second.d_targetStack.erase(aliasPos);
274
275 Logger::getSingleton().logEvent("Window type alias named '" + aliasName + "' removed for window type '" + targetType +"'.");
276
277 // if the list of targets for this alias is now empty
278 if (pos->second.d_targetStack.empty())
279 {
280 // erase the alias name also
281 d_aliasRegistry.erase(aliasName);
282
283 Logger::getSingleton().logEvent("Window type alias named '" + aliasName + "' has no more targets and has been removed.", Informative);
284 }
285
286 }
287
288 }
289
290 }
291
removeAllWindowTypeAliases()292 void WindowFactoryManager::removeAllWindowTypeAliases()
293 {
294 d_aliasRegistry.clear();
295 }
296
addFalagardWindowMapping(const String & newType,const String & targetType,const String & lookName,const String & renderer,const String & effectName)297 void WindowFactoryManager::addFalagardWindowMapping(const String& newType,
298 const String& targetType,
299 const String& lookName,
300 const String& renderer,
301 const String& effectName)
302 {
303 WindowFactoryManager::FalagardWindowMapping mapping;
304 mapping.d_windowType = newType;
305 mapping.d_baseType = targetType;
306 mapping.d_lookName = lookName;
307 mapping.d_rendererType = renderer;
308 mapping.d_effectName = effectName;
309
310 // see if the type we're creating already exists
311 if (d_falagardRegistry.find(newType) != d_falagardRegistry.end())
312 {
313 // type already exists, log the fact that it's going to be replaced.
314 Logger::getSingleton().logEvent("Falagard mapping for type '" + newType + "' already exists - current mapping will be replaced.");
315 }
316
317 char addr_buff[32];
318 sprintf(addr_buff, "(%p)", static_cast<void*>(&mapping));
319 Logger::getSingleton().logEvent("Creating falagard mapping for type '" +
320 newType + "' using base type '" + targetType + "', window renderer '" +
321 renderer + "' Look'N'Feel '" + lookName + "' and RenderEffect '" +
322 effectName + "'. " + addr_buff);
323
324 d_falagardRegistry[newType] = mapping;
325 }
326
removeFalagardWindowMapping(const String & type)327 void WindowFactoryManager::removeFalagardWindowMapping(const String& type)
328 {
329 FalagardMapRegistry::iterator iter = d_falagardRegistry.find(type);
330
331 if (iter != d_falagardRegistry.end())
332 {
333 Logger::getSingleton().logEvent("Removing falagard mapping for type '" + type + "'.");
334 d_falagardRegistry.erase(iter);
335 }
336 }
337
removeAllFalagardWindowMappings()338 void WindowFactoryManager::removeAllFalagardWindowMappings()
339 {
340 d_falagardRegistry.clear();
341 }
342
getFalagardMappingIterator() const343 WindowFactoryManager::FalagardMappingIterator WindowFactoryManager::getFalagardMappingIterator() const
344 {
345 return FalagardMappingIterator(d_falagardRegistry.begin(), d_falagardRegistry.end());
346 }
347
isFalagardMappedType(const String & type) const348 bool WindowFactoryManager::isFalagardMappedType(const String& type) const
349 {
350 return d_falagardRegistry.find(getDereferencedAliasType(type)) != d_falagardRegistry.end();
351 }
352
getMappedLookForType(const String & type) const353 const String& WindowFactoryManager::getMappedLookForType(const String& type) const
354 {
355 FalagardMapRegistry::const_iterator iter =
356 d_falagardRegistry.find(getDereferencedAliasType(type));
357
358 if (iter != d_falagardRegistry.end())
359 {
360 return (*iter).second.d_lookName;
361 }
362 // type does not exist as a mapped type (or an alias for one)
363 else
364 {
365 CEGUI_THROW(InvalidRequestException(
366 "Window factory type '" + type +
367 "' is not a falagard mapped type (or an alias for one)."));
368 }
369 }
370
getMappedRendererForType(const String & type) const371 const String& WindowFactoryManager::getMappedRendererForType(const String& type) const
372 {
373 FalagardMapRegistry::const_iterator iter =
374 d_falagardRegistry.find(getDereferencedAliasType(type));
375
376 if (iter != d_falagardRegistry.end())
377 {
378 return (*iter).second.d_rendererType;
379 }
380 // type does not exist as a mapped type (or an alias for one)
381 else
382 {
383 CEGUI_THROW(InvalidRequestException(
384 "Window factory type '" + type +
385 "' is not a falagard mapped type (or an alias for one)."));
386 }
387 }
388
getDereferencedAliasType(const String & type) const389 String WindowFactoryManager::getDereferencedAliasType(const String& type) const
390 {
391 TypeAliasRegistry::const_iterator alias = d_aliasRegistry.find(type);
392
393 // if this is an aliased type, ensure to fully dereference by recursively
394 // calling ourselves on the active target for the given type.
395 if (alias != d_aliasRegistry.end())
396 return getDereferencedAliasType(alias->second.getActiveTarget());
397
398 // we're not an alias, so return the input type unchanged
399 return type;
400 }
401
getFalagardMappingForType(const String & type) const402 const WindowFactoryManager::FalagardWindowMapping& WindowFactoryManager::getFalagardMappingForType(const String& type) const
403 {
404 FalagardMapRegistry::const_iterator iter =
405 d_falagardRegistry.find(getDereferencedAliasType(type));
406
407 if (iter != d_falagardRegistry.end())
408 {
409 return (*iter).second;
410 }
411 // type does not exist as a mapped type (or an alias for one)
412 else
413 {
414 CEGUI_THROW(InvalidRequestException(
415 "Window factory type '" + type +
416 "' is not a falagard mapped type (or an alias for one)."));
417 }
418 }
419
420
421 //////////////////////////////////////////////////////////////////////////
422 /*************************************************************************
423 Methods for AliasTargetStack class
424 *************************************************************************/
425 //////////////////////////////////////////////////////////////////////////
getActiveTarget(void) const426 const String& WindowFactoryManager::AliasTargetStack::getActiveTarget(void) const
427 {
428 return d_targetStack.back();
429 }
430
431
getStackedTargetCount(void) const432 uint WindowFactoryManager::AliasTargetStack::getStackedTargetCount(void) const
433 {
434 return (uint)d_targetStack.size();
435 }
436
437
438 } // End of CEGUI namespace section
439