Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

CEGUISystem.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUISystem.cpp
00003         created:        20/2/2004
00004         author:         Paul D Turner
00005 
00006         purpose:        Implementation of main system object
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 #ifdef HAVE_CONFIG_H
00027 #   include "config.h"
00028 #endif
00029 
00030 #include "CEGUISystem.h"
00031 #include "CEGUILogger.h"
00032 #include "CEGUIImagesetManager.h"
00033 #include "CEGUIFontManager.h"
00034 #include "CEGUIWindowFactoryManager.h"
00035 #include "CEGUIWindowManager.h"
00036 #include "CEGUISchemeManager.h"
00037 #include "CEGUIMouseCursor.h"
00038 #include "CEGUIWindow.h"
00039 #include "CEGUIImageset.h"
00040 #include "CEGUIExceptions.h"
00041 #include "elements/CEGUIGUISheet.h"
00042 #include "elements/CEGUIDragContainer.h"
00043 #include "elements/CEGUIScrolledContainer.h"
00044 #include "elements/CEGUITooltip.h"
00045 #include "CEGUIScriptModule.h"
00046 #include "CEGUIConfig_xmlHandler.h"
00047 #include "CEGUIDataContainer.h"
00048 #include "CEGUIResourceProvider.h"
00049 #include "CEGUIGlobalEventSet.h"
00050 #include "falagard/CEGUIFalWidgetLookManager.h"
00051 #include "CEGUIPropertyHelper.h"
00052 #include <time.h>
00053 
00054 // set up for whichever default xml parser will be used
00055 #ifdef CEGUI_WITH_XERCES
00056 #   include "CEGUIXercesParser.h"
00057 #   define CEGUI_DEFAULT_XMLPARSER     XercesParser
00058 #else
00059 #   include "CEGUITinyXMLParser.h"
00060 #   define CEGUI_DEFAULT_XMLPARSER     TinyXMLParser
00061 #endif
00062 
00063 
00064 // Start of CEGUI namespace section
00065 namespace CEGUI
00066 {
00067 const String System::EventNamespace("System");
00068 
00073 class SimpleTimer
00074 {
00075         clock_t d_baseTime;
00076 
00077 public:
00078         SimpleTimer() : d_baseTime(clock()) {}
00079 
00080         void    restart()       { d_baseTime = clock(); }
00081         double  elapsed()       { return static_cast<double>(clock() - d_baseTime) / CLOCKS_PER_SEC; }
00082 };
00083 
00089 struct MouseClickTracker
00090 {
00091         MouseClickTracker(void) : d_click_count(0), d_click_area(0, 0, 0, 0) {}
00092 
00093         SimpleTimer             d_timer;                        
00094         int                             d_click_count;          
00095         Rect                    d_click_area;           
00096 };
00097 
00098 
00099 struct MouseClickTrackerImpl
00100 {
00101         MouseClickTracker       click_trackers[MouseButtonCount];
00102 };
00103 
00104 
00105 /*************************************************************************
00106         Constants definitions
00107 *************************************************************************/
00108 const char      System::CEGUIConfigSchemaName[]         = "CEGUIConfig.xsd";
00109 
00110 
00111 /*************************************************************************
00112         Static Data Definitions
00113 *************************************************************************/
00114 // singleton instance pointer
00115 template<> System* Singleton<System>::ms_Singleton      = NULL;
00116 
00117 // click event generation defaults
00118 const double    System::DefaultSingleClickTimeout       = 0.2;
00119 const double    System::DefaultMultiClickTimeout        = 0.33;
00120 const Size              System::DefaultMultiClickAreaSize(12,12);
00121 
00122 // event names
00123 const String System::EventGUISheetChanged( (utf8*)"GUISheetChanged" );
00124 const String System::EventSingleClickTimeoutChanged( (utf8*)"SingleClickTimeoutChanged" );
00125 const String System::EventMultiClickTimeoutChanged( (utf8*)"MultiClickTimeoutChanged" );
00126 const String System::EventMultiClickAreaSizeChanged( (utf8*)"MultiClickAreaSizeChanged" );
00127 const String System::EventDefaultFontChanged( (utf8*)"DefaultFontChanged" );
00128 const String System::EventDefaultMouseCursorChanged( (utf8*)"DefaultMouseCursorChanged" );
00129 const String System::EventMouseMoveScalingChanged( (utf8*)"MouseMoveScalingChanged" );
00130 
00131 
00132 /*************************************************************************
00133         Constructor
00134 *************************************************************************/
00135 System::System(Renderer* renderer, const utf8* logFile) :
00136         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00137 {
00138         constructor_impl(renderer, NULL, NULL, NULL, (const utf8*)"", logFile);
00139 }
00140 /*************************************************************************
00141         Construct a new System object
00142 *************************************************************************/
00143 System::System(Renderer* renderer, ResourceProvider* resourceProvider,const utf8* logFile) :
00144         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00145 {
00146     constructor_impl(renderer, resourceProvider, NULL, NULL, (const utf8*)"", logFile);
00147 }
00148 
00149 /*************************************************************************
00150         Construct a new System object
00151 *************************************************************************/
00152 System::System(Renderer* renderer, ScriptModule* scriptModule, const utf8* configFile) :
00153         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00154 {
00155     constructor_impl(renderer, NULL, NULL, scriptModule, configFile, (const utf8*)"CEGUI.log");
00156 }
00157 
00158 
00159 /*************************************************************************
00160         Construct a new System object
00161 *************************************************************************/
00162 System::System(Renderer* renderer, ScriptModule* scriptModule, ResourceProvider* resourceProvider, const utf8* configFile) :
00163         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00164 {
00165     constructor_impl(renderer, resourceProvider, NULL, scriptModule, configFile, (const utf8*)"CEGUI.log");
00166 }
00167 
00168 /*************************************************************************
00169     Construct a new System object
00170 *************************************************************************/
00171 System::System(Renderer* renderer, XMLParser* xmlParser, const utf8* logFile) :
00172         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00173 {
00174     constructor_impl(renderer, NULL, xmlParser, NULL, (const utf8*)"", logFile);
00175 }
00176 
00177 /*************************************************************************
00178     Construct a new System object
00179 *************************************************************************/
00180 System::System(Renderer* renderer, ResourceProvider* resourceProvider, XMLParser* xmlParser, const utf8* logFile) :
00181         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00182 {
00183     constructor_impl(renderer, resourceProvider, xmlParser, NULL, (const utf8*)"", logFile);
00184 }
00185 
00186 /*************************************************************************
00187     Construct a new System object
00188 *************************************************************************/
00189 System::System(Renderer* renderer, XMLParser* xmlParser, ScriptModule* scriptModule, const utf8* configFile) :
00190         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00191 {
00192     constructor_impl(renderer, NULL, xmlParser, scriptModule, configFile, (const utf8*)"CEGUI.log");
00193 }
00194 
00195 /*************************************************************************
00196     Construct a new System object
00197 *************************************************************************/
00198 System::System(Renderer* renderer, ResourceProvider* resourceProvider, XMLParser* xmlParser, ScriptModule* scriptModule, const utf8* configFile) :
00199         d_clickTrackerPimpl(new MouseClickTrackerImpl)
00200 {
00201     constructor_impl(renderer, resourceProvider, xmlParser, scriptModule, configFile, (const utf8*)"CEGUI.log");
00202 }
00203 
00204 /*************************************************************************
00205         Method to do the work of the constructor
00206 *************************************************************************/
00207 void System::constructor_impl(Renderer* renderer, ResourceProvider* resourceProvider,  XMLParser* xmlParser, ScriptModule* scriptModule, const String& configFile, const String& logFile)
00208 {
00209     // Instantiate logger first (we have no file at this point, but entries will be cached until we do)
00210     new Logger();
00211 
00212     // Set CEGUI version
00213     d_strVersion = PropertyHelper::uintToString(CEGUI_VERSION_MAJOR) + "." +
00214        PropertyHelper::uintToString(CEGUI_VERSION_MINOR) + "." +
00215        PropertyHelper::uintToString(CEGUI_VERSION_PATCH);
00216 
00217         d_renderer              = renderer;
00218         d_gui_redraw    = false;
00219         d_defaultFont   = NULL;
00220         d_wndWithMouse  = NULL;
00221         d_activeSheet   = NULL;
00222         d_modalTarget   = NULL;
00223         d_sysKeys               = 0;
00224 
00225         d_lshift        = false;
00226         d_rshift        = false;
00227         d_lctrl         = false;
00228         d_rctrl         = false;
00229     d_ralt      = false;
00230     d_lalt      = false;
00231 
00232         d_click_timeout         = DefaultSingleClickTimeout;
00233         d_dblclick_timeout      = DefaultMultiClickTimeout;
00234         d_dblclick_size         = DefaultMultiClickAreaSize;
00235 
00236         d_defaultMouseCursor = NULL;
00237         d_scriptModule           = scriptModule;
00238 
00239         d_mouseScalingFactor = 1.0f;
00240 
00241     // Tooltip setup
00242     d_defaultTooltip = 0;
00243     d_weOwnTooltip = false;
00244 
00245         // add events for Sytem object
00246         addSystemEvents();
00247 
00248     // if there has been a resource provider supplied use that otherwise create one.
00249     d_resourceProvider = resourceProvider ? resourceProvider : renderer->createResourceProvider();
00250 
00251     // use supplied xml parser if provided, otherwise create one of the defaults
00252     if (xmlParser)
00253     {
00254         d_xmlParser = xmlParser;
00255         d_ourXmlParser = false;
00256     }
00257     else
00258     {
00259         d_xmlParser = new CEGUI_DEFAULT_XMLPARSER;
00260         d_ourXmlParser = true;
00261     }
00262 
00263     // perform initialisation of XML parser.
00264     d_xmlParser->initialise();
00265 
00266         // strings we may get from the configuration file.
00267         String configLogname, configSchemeName, configLayoutName, configInitScript, defaultFontName;
00268 
00269         // now XML is available, read the configuration file (if any)
00270         if (!configFile.empty())
00271         {
00272         // create handler object
00273         Config_xmlHandler handler;
00274 
00275                 // do parsing of xml file
00276                 try
00277                 {
00278             d_xmlParser->parseXMLFile(handler, configFile, CEGUIConfigSchemaName, "");
00279                 }
00280                 catch(...)
00281                 {
00282                         // cleanup XML stuff
00283             d_xmlParser->cleanup();
00284             delete d_xmlParser;
00285 
00286             throw;
00287                 }
00288 
00289         // set the logging level
00290         Logger::getSingleton().setLoggingLevel(handler.getLoggingLevel());
00291 
00292         // get the strings read
00293         configLogname           = handler.getLogFilename();
00294         configSchemeName        = handler.getSchemeFilename();
00295         configLayoutName        = handler.getLayoutFilename();
00296         defaultFontName         = handler.getDefaultFontName();
00297         configInitScript        = handler.getInitScriptFilename();
00298         d_termScriptName        = handler.getTermScriptFilename();
00299 
00300         // set default resource group if it was specified.
00301         if (!handler.getDefaultResourceGroup().empty())
00302         {
00303             d_resourceProvider->setDefaultResourceGroup(handler.getDefaultResourceGroup());
00304         }
00305         }
00306 
00307         // Start up the logger:
00308         // prefer log filename from config file
00309         if (!configLogname.empty())
00310         {
00311         Logger::getSingleton().setLogFilename(configLogname, false);
00312         }
00313         // no log specified in configuration, use default / hard-coded option
00314         else
00315         {
00316         Logger::getSingleton().setLogFilename(logFile, false);
00317         }
00318 
00319         // beginning main init
00320         Logger::getSingleton().logEvent((utf8*)"---- Begining CEGUI System initialisation ----");
00321 
00322         // cause creation of other singleton objects
00323         new ImagesetManager();
00324         new FontManager();
00325         new WindowFactoryManager();
00326         new WindowManager();
00327         new SchemeManager();
00328         new MouseCursor();
00329         new GlobalEventSet();
00330     new WidgetLookManager();
00331 
00332     // Add factories for types that the system supports natively
00333     // (mainly because they do no rendering)
00334     WindowFactoryManager::getSingleton().addFactory(new GUISheetFactory);
00335     WindowFactoryManager::getSingleton().addFactory(new DragContainerFactory);
00336     WindowFactoryManager::getSingleton().addFactory(new ScrolledContainerFactory);
00337 
00338         // GUISheet's name was changed, register an alias so both can be used
00339         WindowFactoryManager::getSingleton().addWindowTypeAlias((utf8*)"DefaultGUISheet", GUISheet::WidgetTypeName);
00340 
00341         // success - we are created!  Log it for prosperity :)
00342         Logger::getSingleton().logEvent((utf8*)"CEGUI::System singleton created.");
00343         Logger::getSingleton().logEvent((utf8*)"---- CEGUI System initialisation completed ----");
00344     Logger::getSingleton().logEvent((utf8*)"---- Version " + d_strVersion + " ----");
00345     Logger::getSingleton().logEvent("---- Renderer module is: " + d_renderer->getIdentifierString() + " ----");
00346     Logger::getSingleton().logEvent("---- XML Parser module is: " + d_xmlParser->getIdentifierString() + " ----");
00347     Logger::getSingleton().logEvent(d_scriptModule ? "---- Scripting module is: " + d_scriptModule->getIdentifierString() + " ----" : "---- Scripting module is: None ----");
00348         // subscribe to hear about display mode changes
00349         d_renderer->subscribeEvent(Renderer::EventDisplaySizeChanged, Event::Subscriber(&CEGUI::System::handleDisplaySizeChange, this));
00350 
00351         // load base scheme
00352         if (!configSchemeName.empty())
00353         {
00354                 try
00355                 {
00356                         SchemeManager::getSingleton().loadScheme(configSchemeName, d_resourceProvider->getDefaultResourceGroup());
00357 
00358                         // set default font if that was specified also
00359                         if (!defaultFontName.empty())
00360                         {
00361                                 setDefaultFont(defaultFontName);
00362                         }
00363 
00364                 }
00365                 catch (CEGUI::Exception exc) {}  // catch exception and try to continue anyway
00366 
00367         }
00368 
00369         // load initial layout
00370         if (!configLayoutName.empty())
00371         {
00372                 try
00373                 {
00374                         setGUISheet(WindowManager::getSingleton().loadWindowLayout(configLayoutName));
00375                 }
00376                 catch (CEGUI::Exception exc) {}  // catch exception and try to continue anyway
00377 
00378         }
00379 
00380     // Create script module bindings
00381     if (d_scriptModule)
00382     {
00383         d_scriptModule->createBindings();
00384     }
00385 
00386         // execute start up script
00387         if (!configInitScript.empty())
00388         {
00389                 try
00390                 {
00391                         executeScriptFile(configInitScript);
00392                 }
00393                 catch (...) {}  // catch all exceptions and try to continue anyway
00394 
00395         }
00396 
00397 }
00398 
00399 
00400 /*************************************************************************
00401         Destructor
00402 *************************************************************************/
00403 System::~System(void)
00404 {
00405         Logger::getSingleton().logEvent((utf8*)"---- Begining CEGUI System destruction ----");
00406 
00407         // execute shut-down script
00408         if (!d_termScriptName.empty())
00409         {
00410                 try
00411                 {
00412                         executeScriptFile(d_termScriptName);
00413                 }
00414                 catch (...) {}  // catch all exceptions and continue system shutdown
00415 
00416         }
00417 
00418     // Cleanup script module bindings
00419     if (d_scriptModule)
00420     {
00421         d_scriptModule->destroyBindings();
00422     }
00423 
00424         // cleanup XML stuff
00425     if (d_xmlParser)
00426     {
00427         d_xmlParser->cleanup();
00428         if (d_ourXmlParser)
00429             delete d_xmlParser;
00430     }
00431 
00432     //
00433         // perform cleanup in correct sequence
00434         //
00435         // destroy windows so it's safe to destroy factories
00436     WindowManager::getSingleton().destroyAllWindows();
00437     WindowManager::getSingleton().cleanDeadPool();
00438 
00439         // get pointers to the factories we added
00440         WindowFactory* guiSheetFactory =
00441         WindowFactoryManager::getSingleton().getFactory(GUISheet::WidgetTypeName);
00442 
00443     WindowFactory* dragContainerFactory =
00444         WindowFactoryManager::getSingleton().getFactory(DragContainer::WidgetTypeName);
00445 
00446     WindowFactory* scrolledContainerFactory =
00447         WindowFactoryManager::getSingleton().getFactory(ScrolledContainer::WidgetTypeName);
00448 
00449     // remove factories so it's safe to unload GUI modules
00450         WindowFactoryManager::getSingleton().removeAllFactories();
00451 
00452         // destroy factories we created
00453         delete guiSheetFactory;
00454     delete dragContainerFactory;
00455     delete scrolledContainerFactory;
00456 
00457         // cleanup singletons
00458         delete  SchemeManager::getSingletonPtr();
00459         delete  WindowManager::getSingletonPtr();
00460         delete  WindowFactoryManager::getSingletonPtr();
00461     delete  WidgetLookManager::getSingletonPtr();
00462         delete  FontManager::getSingletonPtr();
00463         delete  MouseCursor::getSingletonPtr();
00464         delete  ImagesetManager::getSingletonPtr();
00465         delete  GlobalEventSet::getSingletonPtr();
00466 
00467         Logger::getSingleton().logEvent((utf8*)"CEGUI::System singleton destroyed.");
00468         Logger::getSingleton().logEvent((utf8*)"---- CEGUI System destruction completed ----");
00469         delete Logger::getSingletonPtr();
00470 
00471         delete d_clickTrackerPimpl;
00472 }
00473 
00474 
00475 /*************************************************************************
00476         Render the GUI for this frame
00477 *************************************************************************/
00478 void System::renderGUI(void)
00479 {
00481         // This makes use of some tricks the Renderer can do so that we do not
00482         // need to do a full redraw every frame - only when some UI element has
00483         // changed.
00484         //
00485         // Since the mouse is likely to move very often, and in order not to
00486         // short-circuit the above optimisation, the mouse is not queued, but is
00487         // drawn directly to the display every frame.
00489 
00490         if (d_gui_redraw)
00491         {
00492                 d_renderer->resetZValue();
00493                 d_renderer->setQueueingEnabled(true);
00494                 d_renderer->clearRenderList();
00495 
00496                 if (d_activeSheet != NULL)
00497                 {
00498                         d_activeSheet->render();
00499                 }
00500 
00501                 d_gui_redraw = false;
00502         }
00503 
00504         d_renderer->doRender();
00505 
00506         // draw mouse
00507         d_renderer->setQueueingEnabled(false);
00508         MouseCursor::getSingleton().draw();
00509 
00510     // do final destruction on dead-pool windows
00511     WindowManager::getSingleton().cleanDeadPool();
00512 }
00513 
00514 
00515 /*************************************************************************
00516         Set the active GUI sheet (root) window.
00517 *************************************************************************/
00518 Window* System::setGUISheet(Window* sheet)
00519 {
00520         Window* old = d_activeSheet;
00521         d_activeSheet = sheet;
00522 
00523     // Force and update for the area Rects for 'sheet' so they're correct according
00524     // to the screen size.
00525     if (sheet != 0)
00526     {
00527         WindowEventArgs sheetargs(0);
00528         sheet->onParentSized(sheetargs);
00529     }
00530 
00531         // fire event
00532         WindowEventArgs args(old);
00533         onGUISheetChanged(args);
00534 
00535         return old;
00536 }
00537 
00538 
00539 /*************************************************************************
00540         Set the default font to be used by the system
00541 *************************************************************************/
00542 void System::setDefaultFont(const String& name)
00543 {
00544         if (name.empty())
00545         {
00546                 setDefaultFont(NULL);
00547         }
00548         else
00549         {
00550                 setDefaultFont(FontManager::getSingleton().getFont(name));
00551         }
00552 
00553 }
00554 
00555 
00556 /*************************************************************************
00557         Set the default font to be used by the system
00558 *************************************************************************/
00559 void System::setDefaultFont(Font* font)
00560 {
00561         d_defaultFont = font;
00562 
00563         // fire event
00564         EventArgs args;
00565         onDefaultFontChanged(args);
00566 }
00567 
00568 
00569 /*************************************************************************
00570         Set the image to be used as the default mouse cursor.
00571 *************************************************************************/
00572 void System::setDefaultMouseCursor(const Image* image)
00573 {
00574         if (image == (const Image*)DefaultMouseCursor)
00575         {
00576                 image = NULL;
00577         }
00578 
00579         d_defaultMouseCursor = image;
00580 
00581         // fire off event.
00582         EventArgs args;
00583         onDefaultMouseCursorChanged(args);
00584 }
00585 
00586 
00587 /*************************************************************************
00588         Set the image to be used as the default mouse cursor.
00589 *************************************************************************/
00590 void System::setDefaultMouseCursor(const String& imageset, const String& image_name)
00591 {
00592         setDefaultMouseCursor(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image_name));
00593 }
00594 
00595 
00596 /*************************************************************************
00597         Return a pointer to the ScriptModule being used for scripting within
00598         the GUI system.
00599 *************************************************************************/
00600 ScriptModule* System::getScriptingModule(void) const
00601 {
00602         return d_scriptModule;
00603 }
00604 
00605 /*************************************************************************
00606         Return a pointer to the ResourceProvider being used for within the GUI
00607     system.
00608 *************************************************************************/
00609 ResourceProvider* System::getResourceProvider(void) const
00610 {
00611         return d_resourceProvider;
00612 }
00613 
00614 /*************************************************************************
00615         Execute a script file if possible.
00616 *************************************************************************/
00617 void System::executeScriptFile(const String& filename, const String& resourceGroup) const
00618 {
00619         if (d_scriptModule != NULL)
00620         {
00621                 try
00622                 {
00623                         d_scriptModule->executeScriptFile(filename, resourceGroup);
00624                 }
00625                 catch(...)
00626                 {
00627                         throw GenericException((utf8*)"System::executeScriptFile - An exception was thrown during the execution of the script file.");
00628                 }
00629 
00630         }
00631         else
00632         {
00633                 Logger::getSingleton().logEvent((utf8*)"System::executeScriptFile - the script named '" + filename +"' could not be executed as no ScriptModule is available.", Errors);
00634         }
00635 
00636 }
00637 
00638 
00639 /*************************************************************************
00640         Execute a scripted global function if possible.  The function should
00641         not take any parameters and should return an integer.
00642 *************************************************************************/
00643 int     System::executeScriptGlobal(const String& function_name) const
00644 {
00645         if (d_scriptModule != NULL)
00646         {
00647                 try
00648                 {
00649                         return d_scriptModule->executeScriptGlobal(function_name);
00650                 }
00651                 catch(...)
00652                 {
00653                         throw GenericException((utf8*)"System::executeScriptGlobal - An exception was thrown during execution of the scripted function.");
00654                 }
00655 
00656         }
00657         else
00658         {
00659                 Logger::getSingleton().logEvent((utf8*)"System::executeScriptGlobal - the global script function named '" + function_name +"' could not be executed as no ScriptModule is available.", Errors);
00660         }
00661 
00662         return 0;
00663 }
00664 
00665 
00666 /*************************************************************************
00667     If possible, execute script code contained in the given
00668     CEGUI::String object.
00669 *************************************************************************/
00670 void System::executeScriptString(const String& str) const
00671 {
00672     if (d_scriptModule != NULL)
00673     {
00674         try
00675         {
00676             d_scriptModule->executeString(str);
00677         }
00678         catch(...)
00679         {
00680             throw GenericException((utf8*)"System::executeScriptString - An exception was thrown during execution of the script code.");
00681         }
00682 
00683     }
00684     else
00685     {
00686         Logger::getSingleton().logEvent((utf8*)"System::executeScriptString - the script code could not be executed as no ScriptModule is available.", Errors);
00687     }
00688 }
00689 
00690 
00691 /*************************************************************************
00692         return the current mouse movement scaling factor.
00693 *************************************************************************/
00694 float System::getMouseMoveScaling(void) const
00695 {
00696         return d_mouseScalingFactor;
00697 }
00698 
00699 
00700 /*************************************************************************
00701         Set the current mouse movement scaling factor
00702 *************************************************************************/
00703 void System::setMouseMoveScaling(float scaling)
00704 {
00705         d_mouseScalingFactor = scaling;
00706 
00707         // fire off event.
00708         EventArgs args;
00709         onMouseMoveScalingChanged(args);
00710 }
00711 
00712 
00713 /*************************************************************************
00714         Method that injects a mouse movement event into the system
00715 *************************************************************************/
00716 bool System::injectMouseMove(float delta_x, float delta_y)
00717 {
00718         MouseEventArgs ma(NULL);
00719         MouseCursor& mouse = MouseCursor::getSingleton();
00720 
00721         ma.moveDelta.d_x = delta_x * d_mouseScalingFactor;
00722         ma.moveDelta.d_y = delta_y * d_mouseScalingFactor;
00723         ma.sysKeys = d_sysKeys;
00724         ma.wheelChange = 0;
00725         ma.clickCount = 0;
00726 
00727         // move the mouse cursor & update position in args.
00728         mouse.offsetPosition(ma.moveDelta);
00729         ma.position = mouse.getPosition();
00730 
00731         Window* dest_window = getTargetWindow(ma.position);
00732 
00733         // if there is no GUI sheet, then there is nowhere to send input
00734         if (dest_window != NULL)
00735         {
00736                 if (dest_window != d_wndWithMouse)
00737                 {
00738                         if (d_wndWithMouse != NULL)
00739                         {
00740                                 ma.window = d_wndWithMouse;
00741                                 d_wndWithMouse->onMouseLeaves(ma);
00742                         }
00743 
00744                         d_wndWithMouse = dest_window;
00745                         ma.window = dest_window;
00746                         dest_window->onMouseEnters(ma);
00747                 }
00748 
00749                 // ensure event starts as 'not handled'
00750                 ma.handled = false;
00751 
00752                 // loop backwards until event is handled or we run out of windows.
00753                 while ((!ma.handled) && (dest_window != NULL))
00754                 {
00755                         ma.window = dest_window;
00756                         dest_window->onMouseMove(ma);
00757                         dest_window = getNextTargetWindow(dest_window);
00758                 }
00759 
00760         }
00761 
00762         return ma.handled;
00763 }
00764 
00765 
00766 /*************************************************************************
00767         Method that injects that the mouse is leaves the application window
00768 *************************************************************************/
00769 bool System::injectMouseLeaves(void)
00770 {
00771         MouseEventArgs ma(NULL);
00772 
00773         // if there is no window that currently contains the mouse, then
00774         // there is nowhere to send input
00775         if (d_wndWithMouse != NULL)
00776         {
00777                 ma.position = MouseCursor::getSingleton().getPosition();
00778                 ma.moveDelta = Vector2(0.0f, 0.0f);
00779                 ma.button = NoButton;
00780                 ma.sysKeys = d_sysKeys;
00781                 ma.wheelChange = 0;
00782                 ma.window = d_wndWithMouse;
00783                 ma.clickCount = 0;
00784 
00785                 d_wndWithMouse->onMouseLeaves(ma);
00786                 d_wndWithMouse = NULL;
00787         }
00788 
00789         return ma.handled;
00790 }
00791 
00792 
00793 /*************************************************************************
00794         Method that injects a mouse button down event into the system.
00795 *************************************************************************/
00796 bool System::injectMouseButtonDown(MouseButton button)
00797 {
00798         // update system keys
00799         d_sysKeys |= mouseButtonToSyskey(button);
00800 
00801         MouseEventArgs ma(NULL);
00802         ma.position = MouseCursor::getSingleton().getPosition();
00803         ma.moveDelta = Vector2(0.0f, 0.0f);
00804         ma.button = button;
00805         ma.sysKeys = d_sysKeys;
00806         ma.wheelChange = 0;
00807 
00808         //
00809         // Handling for multi-click generation
00810         //
00811         MouseClickTracker& tkr = d_clickTrackerPimpl->click_trackers[button];
00812 
00813         tkr.d_click_count++;
00814 
00815         // see if we meet multi-click timing
00816         if ((tkr.d_timer.elapsed() > d_dblclick_timeout) ||
00817                 (!tkr.d_click_area.isPointInRect(ma.position)) ||
00818                 (tkr.d_click_count > 3))
00819         {
00820                 // single down event.
00821                 tkr.d_click_count = 1;
00822 
00823                 // build allowable area for multi-clicks
00824                 tkr.d_click_area.setPosition(ma.position);
00825                 tkr.d_click_area.setSize(d_dblclick_size);
00826                 tkr.d_click_area.offset(Point(-(d_dblclick_size.d_width / 2), -(d_dblclick_size.d_height / 2)));
00827         }
00828 
00829         // set click count in the event args
00830         ma.clickCount = tkr.d_click_count;
00831 
00832         Window* dest_window = getTargetWindow(ma.position);
00833 
00834         // loop backwards until event is handled or we run out of windows.
00835         while ((!ma.handled) && (dest_window != NULL))
00836         {
00837                 ma.window = dest_window;
00838 
00839         if (dest_window->wantsMultiClickEvents())
00840         {
00841             switch (tkr.d_click_count)
00842             {
00843             case 1:
00844                 dest_window->onMouseButtonDown(ma);
00845                 break;
00846 
00847             case 2:
00848                 dest_window->onMouseDoubleClicked(ma);
00849                 break;
00850 
00851             case 3:
00852                 dest_window->onMouseTripleClicked(ma);
00853                 break;
00854             }
00855         }
00856         // current target window does not want multi-clicks,
00857         // so just send a mouse down event instead.
00858         else
00859         {
00860             dest_window->onMouseButtonDown(ma);
00861         }
00862 
00863                 dest_window = getNextTargetWindow(dest_window);
00864         }
00865 
00866         // reset timer for this tracker.
00867         tkr.d_timer.restart();
00868 
00869         return ma.handled;
00870 }
00871 
00872 
00873 /*************************************************************************
00874         Method that injects a mouse button up event into the system.
00875 *************************************************************************/
00876 bool System::injectMouseButtonUp(MouseButton button)
00877 {
00878         // update system keys
00879         d_sysKeys &= ~mouseButtonToSyskey(button);
00880 
00881         MouseEventArgs ma(NULL);
00882         ma.position = MouseCursor::getSingleton().getPosition();
00883         ma.moveDelta = Vector2(0.0f, 0.0f);
00884         ma.button = button;
00885         ma.sysKeys = d_sysKeys;
00886         ma.wheelChange = 0;
00887 
00888     // get the tracker that holds the number of down events seen so far for this button
00889     MouseClickTracker& tkr = d_clickTrackerPimpl->click_trackers[button];
00890     // set click count in the event args
00891     ma.clickCount = tkr.d_click_count;
00892 
00893         Window* dest_window = getTargetWindow(ma.position);
00894 
00895         // loop backwards until event is handled or we run out of windows.
00896         while ((!ma.handled) && (dest_window != NULL))
00897         {
00898                 ma.window = dest_window;
00899                 dest_window->onMouseButtonUp(ma);
00900                 dest_window = getNextTargetWindow(dest_window);
00901         }
00902 
00903         bool wasUpHandled = ma.handled;
00904 
00905         // check timer for 'button' to see if this up event also constitutes a single 'click'
00906         if (tkr.d_timer.elapsed() <= d_click_timeout)
00907         {
00908                 ma.handled = false;
00909                 dest_window = getTargetWindow(ma.position);
00910 
00911                 // loop backwards until event is handled or we run out of windows.
00912                 while ((!ma.handled) && (dest_window != NULL))
00913                 {
00914                         ma.window = dest_window;
00915                         dest_window->onMouseClicked(ma);
00916                         dest_window = getNextTargetWindow(dest_window);
00917                 }
00918 
00919         }
00920 
00921         return (ma.handled | wasUpHandled);
00922 }
00923 
00924 
00925 /*************************************************************************
00926         Method that injects a key down event into the system.
00927 *************************************************************************/
00928 bool System::injectKeyDown(uint key_code)
00929 {
00930         // update system keys
00931         d_sysKeys |= keyCodeToSyskey((Key::Scan)key_code, true);
00932 
00933         KeyEventArgs args(NULL);
00934 
00935         if (d_activeSheet != NULL)
00936         {
00937                 args.scancode = (Key::Scan)key_code;
00938                 args.sysKeys = d_sysKeys;
00939 
00940                 Window* dest = getKeyboardTargetWindow();
00941 
00942                 // loop backwards until event is handled or we run out of windows.
00943                 while ((dest != NULL) && (!args.handled))
00944                 {
00945                         args.window = dest;
00946                         dest->onKeyDown(args);
00947                         dest = getNextTargetWindow(dest);
00948                 }
00949 
00950         }
00951 
00952         return args.handled;
00953 }
00954 
00955 
00956 /*************************************************************************
00957         Method that injects a key up event into the system.
00958 *************************************************************************/
00959 bool System::injectKeyUp(uint key_code)
00960 {
00961         // update system keys
00962         d_sysKeys &= ~keyCodeToSyskey((Key::Scan)key_code, false);
00963 
00964         KeyEventArgs args(NULL);
00965 
00966         if (d_activeSheet != NULL)
00967         {
00968                 args.scancode = (Key::Scan)key_code;
00969                 args.sysKeys = d_sysKeys;
00970 
00971                 Window* dest = getKeyboardTargetWindow();
00972 
00973                 // loop backwards until event is handled or we run out of windows.
00974                 while ((dest != NULL) && (!args.handled))
00975                 {
00976                         args.window = dest;
00977                         dest->onKeyUp(args);
00978                         dest = getNextTargetWindow(dest);
00979                 }
00980 
00981         }
00982 
00983         return args.handled;
00984 }
00985 
00986 
00987 /*************************************************************************
00988         Method that injects a typed character event into the system.
00989 *************************************************************************/
00990 bool System::injectChar(utf32 code_point)
00991 {
00992         KeyEventArgs args(NULL);
00993 
00994         if (d_activeSheet != NULL)
00995         {
00996                 args.codepoint = code_point;
00997                 args.sysKeys = d_sysKeys;
00998 
00999                 Window* dest = getKeyboardTargetWindow();
01000 
01001                 // loop backwards until event is handled or we run out of windows.
01002                 while ((dest != NULL) && (!args.handled))
01003                 {
01004                         args.window = dest;
01005                         dest->onCharacter(args);
01006                         dest = getNextTargetWindow(dest);
01007                 }
01008 
01009         }
01010 
01011         return args.handled;
01012 }
01013 
01014 
01015 /*************************************************************************
01016         Method that injects a mouse-wheel / scroll-wheel event into the system.
01017 *************************************************************************/
01018 bool System::injectMouseWheelChange(float delta)
01019 {
01020         MouseEventArgs ma(NULL);
01021         ma.position = MouseCursor::getSingleton().getPosition();
01022         ma.moveDelta = Vector2(0.0f, 0.0f);
01023         ma.button = NoButton;
01024         ma.sysKeys = d_sysKeys;
01025         ma.wheelChange = delta;
01026         ma.clickCount = 0;
01027 
01028         Window* dest_window = getTargetWindow(ma.position);
01029 
01030         // loop backwards until event is handled or we run out of windows.
01031         while ((!ma.handled) && (dest_window != NULL))
01032         {
01033                 ma.window = dest_window;
01034                 dest_window->onMouseWheel(ma);
01035                 dest_window = getNextTargetWindow(dest_window);
01036         }
01037 
01038         return ma.handled;
01039 }
01040 
01041 
01042 /*************************************************************************
01043         Method that injects a new position for the mouse cursor.
01044 *************************************************************************/
01045 bool System::injectMousePosition(float x_pos, float y_pos)
01046 {
01047         // set new mouse position
01048         MouseCursor::getSingleton().setPosition(Point(x_pos, y_pos));
01049 
01050         // do the real work
01051         return injectMouseMove(0, 0);
01052 }
01053 
01054 
01055 /*************************************************************************
01056         Method to inject time pulses into the system.
01057 *************************************************************************/
01058 bool System::injectTimePulse(float timeElapsed)
01059 {
01060         if (d_activeSheet != NULL)
01061         {
01062                 d_activeSheet->update(timeElapsed);
01063         }
01064 
01065         return true;
01066 }
01067 
01068 
01069 /*************************************************************************
01070         Return window that should get mouse inouts when mouse it at 'pt'
01071 *************************************************************************/
01072 Window* System::getTargetWindow(const Point& pt) const
01073 {
01074         Window* dest_window = NULL;
01075 
01076         // if there is no GUI sheet, then there is nowhere to send input
01077         if (d_activeSheet != NULL)
01078         {
01079                 dest_window = Window::getCaptureWindow();
01080 
01081                 if (dest_window == NULL)
01082                 {
01083                         dest_window = d_activeSheet->getChildAtPosition(pt);
01084 
01085                         if (dest_window == NULL)
01086                         {
01087                                 dest_window = d_activeSheet;
01088                         }
01089 
01090                 }
01091                 else
01092                 {
01093             if (dest_window->distributesCapturedInputs())
01094             {
01095                 Window* child_window = dest_window->getChildAtPosition(pt);
01096 
01097                 if (child_window != NULL)
01098                 {
01099                     dest_window = child_window;
01100                 }
01101 
01102             }
01103 
01104                 }
01105 
01106                 // modal target overrules
01107                 if (d_modalTarget != NULL && dest_window != d_modalTarget)
01108                 {
01109                         if (!dest_window->isAncestor(d_modalTarget))
01110                         {
01111                                 dest_window = d_modalTarget;
01112                         }
01113 
01114                 }
01115 
01116         }
01117 
01118         return dest_window;
01119 }
01120 
01121 
01122 /*************************************************************************
01123         Return window that should receive keyboard input
01124 *************************************************************************/
01125 Window* System::getKeyboardTargetWindow(void) const
01126 {
01127         Window* target = NULL;
01128 
01129         if (d_modalTarget == NULL)
01130         {
01131                 target = d_activeSheet->getActiveChild();
01132         }
01133         else
01134         {
01135                 target = d_modalTarget->getActiveChild();
01136                 if (target == NULL)
01137                 {
01138                         target = d_modalTarget;
01139                 }
01140         }
01141 
01142         return target;
01143 }
01144 
01145 
01146 /*************************************************************************
01147         Return the next window that should receive input in the chain
01148 *************************************************************************/
01149 Window* System::getNextTargetWindow(Window* w) const
01150 {
01151         // if we have not reached the modal target, return the parent
01152         if (w != d_modalTarget)
01153         {
01154                 return w->getParent();
01155         }
01156 
01157         // otherwise stop now
01158         return NULL;
01159 }
01160 
01161 
01162 /*************************************************************************
01163         Translate a MouseButton value into the corresponding SystemKey value
01164 *************************************************************************/
01165 SystemKey System::mouseButtonToSyskey(MouseButton btn) const
01166 {
01167         switch (btn)
01168         {
01169         case LeftButton:
01170                 return LeftMouse;
01171 
01172         case RightButton:
01173                 return RightMouse;
01174 
01175         case MiddleButton:
01176                 return MiddleMouse;
01177 
01178         case X1Button:
01179                 return X1Mouse;
01180 
01181         case X2Button:
01182                 return X2Mouse;
01183 
01184         default:
01185                 throw InvalidRequestException((utf8*)"System::mouseButtonToSyskey - the parameter 'btn' is not a valid MouseButton value.");
01186         }
01187 }
01188 
01189 
01190 /*************************************************************************
01191         Translate a Key::Scan value into the corresponding SystemKey value
01192 *************************************************************************/
01193 SystemKey System::keyCodeToSyskey(Key::Scan key, bool direction)
01194 {
01195         switch (key)
01196         {
01197         case Key::LeftShift:
01198                 d_lshift = direction;
01199 
01200                 if (!d_rshift)
01201                 {
01202                         return Shift;
01203                 }
01204                 break;
01205 
01206         case Key::RightShift:
01207                 d_rshift = direction;
01208 
01209                 if (!d_lshift)
01210                 {
01211                         return Shift;
01212                 }
01213                 break;
01214 
01215 
01216         case Key::LeftControl:
01217                 d_lctrl = direction;
01218 
01219                 if (!d_rctrl)
01220                 {
01221                         return Control;
01222                 }
01223                 break;
01224 
01225         case Key::RightControl:
01226                 d_rctrl = direction;
01227 
01228                 if (!d_lctrl)
01229                 {
01230                         return Control;
01231                 }
01232                 break;
01233 
01234         case Key::LeftAlt:
01235                 d_lalt = direction;
01236 
01237                 if (!d_ralt)
01238                 {
01239                         return Alt;
01240                 }
01241                 break;
01242 
01243         case Key::RightAlt:
01244                 d_ralt = direction;
01245 
01246                 if (!d_lalt)
01247                 {
01248                         return Alt;
01249                 }
01250                 break;
01251 
01252     default:
01253         break;
01254         }
01255 
01256         // if not a system key or overall state unchanged, return 0.
01257         return (SystemKey)0;
01258 }
01259 
01260 
01261 System& System::getSingleton(void)
01262 {
01263         return Singleton<System>::getSingleton();
01264 }
01265 
01266 
01267 System* System::getSingletonPtr(void)
01268 {
01269         return Singleton<System>::getSingletonPtr();
01270 }
01271 
01272 
01273 
01274 /*************************************************************************
01275         Set the timeout to be used for the generation of single-click events.
01276 *************************************************************************/
01277 void System::setSingleClickTimeout(double timeout)
01278 {
01279         d_click_timeout = timeout;
01280 
01281         // fire off event.
01282         EventArgs args;
01283         onSingleClickTimeoutChanged(args);
01284 }
01285 
01286 
01287 /*************************************************************************
01288         Set the timeout to be used for the generation of multi-click events.
01289 *************************************************************************/
01290 void System::setMultiClickTimeout(double timeout)
01291 {
01292         d_dblclick_timeout = timeout;
01293 
01294         // fire off event.
01295         EventArgs args;
01296         onMultiClickTimeoutChanged(args);
01297 }
01298 
01299 
01300 /*************************************************************************
01301         Set the size of the allowable mouse movement tolerance used when
01302         generating multi-click events.
01303 *************************************************************************/
01304 void System::setMultiClickToleranceAreaSize(const Size& sz)
01305 {
01306         d_dblclick_size = sz;
01307 
01308         // fire off event.
01309         EventArgs args;
01310         onMultiClickAreaSizeChanged(args);
01311 }
01312 
01313 
01314 /*************************************************************************
01315         add events for the System object
01316 *************************************************************************/
01317 void System::addSystemEvents(void)
01318 {
01319         addEvent(EventGUISheetChanged);
01320         addEvent(EventSingleClickTimeoutChanged);
01321         addEvent(EventMultiClickTimeoutChanged);
01322         addEvent(EventMultiClickAreaSizeChanged);
01323         addEvent(EventDefaultFontChanged);
01324         addEvent(EventDefaultMouseCursorChanged);
01325         addEvent(EventMouseMoveScalingChanged);
01326 }
01327 
01328 
01329 /*************************************************************************
01330         Handler called when the main system GUI Sheet (or root window) is changed
01331 *************************************************************************/
01332 void System::onGUISheetChanged(WindowEventArgs& e)
01333 {
01334         fireEvent(EventGUISheetChanged, e, EventNamespace);
01335 }
01336 
01337 
01338 /*************************************************************************
01339         Handler called when the single-click timeout value is changed.
01340 *************************************************************************/
01341 void System::onSingleClickTimeoutChanged(EventArgs& e)
01342 {
01343         fireEvent(EventSingleClickTimeoutChanged, e, EventNamespace);
01344 }
01345 
01346 
01347 /*************************************************************************
01348         Handler called when the multi-click timeout value is changed.
01349 *************************************************************************/
01350 void System::onMultiClickTimeoutChanged(EventArgs& e)
01351 {
01352         fireEvent(EventMultiClickTimeoutChanged, e, EventNamespace);
01353 }
01354 
01355 
01356 /*************************************************************************
01357         Handler called when the size of the multi-click tolerance area is
01358         changed.
01359 *************************************************************************/
01360 void System::onMultiClickAreaSizeChanged(EventArgs& e)
01361 {
01362         fireEvent(EventMultiClickAreaSizeChanged, e, EventNamespace);
01363 }
01364 
01365 
01366 /*************************************************************************
01367         Handler called when the default system font is changed.
01368 *************************************************************************/
01369 void System::onDefaultFontChanged(EventArgs& e)
01370 {
01371         fireEvent(EventDefaultFontChanged, e, EventNamespace);
01372 }
01373 
01374 
01375 /*************************************************************************
01376         Handler called when the default system mouse cursor image is changed.
01377 *************************************************************************/
01378 void System::onDefaultMouseCursorChanged(EventArgs& e)
01379 {
01380         fireEvent(EventDefaultMouseCursorChanged, e, EventNamespace);
01381 }
01382 
01383 
01384 /*************************************************************************
01385         Handler called when the mouse movement scaling factor is changed.
01386 *************************************************************************/
01387 void System::onMouseMoveScalingChanged(EventArgs& e)
01388 {
01389         fireEvent(EventMouseMoveScalingChanged, e, EventNamespace);
01390 }
01391 
01392 
01393 /*************************************************************************
01394         Handler method for display size change notifications
01395 *************************************************************************/
01396 bool System::handleDisplaySizeChange(const EventArgs& e)
01397 {
01398         // notify the imageset/font manager of the size change
01399         Size new_sz = getRenderer()->getSize();
01400         ImagesetManager::getSingleton().notifyScreenResolution(new_sz);
01401         FontManager::getSingleton().notifyScreenResolution(new_sz);
01402 
01403         // notify gui sheet / root if size change, event propagation will ensure everything else
01404         // gets updated as required.
01405         if (d_activeSheet != NULL)
01406         {
01407                 WindowEventArgs args(NULL);
01408                 d_activeSheet->onParentSized(args);
01409         }
01410 
01411         return true;
01412 }
01413 
01414 
01415 /*************************************************************************
01416         Internal method used to inform the System object whenever a window is
01417         destroyed, so that System can perform any required housekeeping.
01418 *************************************************************************/
01419 void System::notifyWindowDestroyed(const Window* window)
01420 {
01421         if (d_wndWithMouse == window)
01422         {
01423                 d_wndWithMouse = NULL;
01424         }
01425 
01426         if (d_activeSheet == window)
01427         {
01428                 d_activeSheet = NULL;
01429         }
01430 
01431         if (d_modalTarget == window)
01432         {
01433                 d_modalTarget = NULL;
01434         }
01435 
01436 }
01437 
01438 void System::setTooltip(Tooltip* tooltip)
01439 {
01440     // destroy current custom tooltip if one exists and we created it
01441     if (d_defaultTooltip && d_weOwnTooltip)
01442         WindowManager::getSingleton().destroyWindow(d_defaultTooltip);
01443 
01444     // set new custom tooltip 
01445     d_weOwnTooltip = false;
01446     d_defaultTooltip = tooltip;
01447 }
01448 
01449 void System::setTooltip(const String& tooltipType)
01450 {
01451     // destroy current tooltip if one exists and we created it
01452     if (d_defaultTooltip && d_weOwnTooltip)
01453         WindowManager::getSingleton().destroyWindow(d_defaultTooltip);
01454 
01455     if (tooltipType.empty())
01456     {
01457         d_defaultTooltip = 0;
01458         d_weOwnTooltip = false;
01459     }
01460     else
01461     {
01462         try
01463         {
01464             d_defaultTooltip = static_cast<Tooltip*>(WindowManager::getSingleton().createWindow(tooltipType, "CEGUI::System::default__auto_tooltip__"));
01465             d_weOwnTooltip = true;
01466         }
01467         catch(UnknownObjectException x)
01468         {
01469             d_defaultTooltip = 0;
01470             d_weOwnTooltip = false;
01471         }
01472     }
01473 }
01474 
01475 } // End of  CEGUI namespace section

Generated on Wed Sep 7 09:56:34 2005 for Crazy Eddies GUI System by  doxygen 1.4.3