text: /**
   * Ext JS Library
   * Copyright(c) 2006-2014 Sencha Inc.
   * licensing@sencha.com
   * http://www.sencha.com/license
   * @class Ext.ux.desktop.App
   */
  Ext.define('Ext.ux.desktop.App', {
      mixins: {
          observable: 'Ext.util.Observable'
      },
  
      requires: [
          'Ext.container.Viewport',
  
          'Ext.ux.desktop.Desktop'
      ],
  
      isReady: false,
      modules: null,
      useQuickTips: true,
  
      constructor: function (config) {
          var me = this;
  
          me.mixins.observable.constructor.call(this, config);
  
          if (Ext.isReady) {
              Ext.Function.defer(me.init, 10, me);
          } else {
              Ext.onReady(me.init, me);
          }
      },
  
      init: function() {
          var me = this, desktopCfg;
  
          if (me.useQuickTips) {
              Ext.QuickTips.init();
          }
  
          me.modules = me.getModules();
          if (me.modules) {
              me.initModules(me.modules);
          }
  
          desktopCfg = me.getDesktopConfig();
          me.desktop = new Ext.ux.desktop.Desktop(desktopCfg);
  
          me.viewport = new Ext.container.Viewport({
              layout: 'fit',
              items: [ me.desktop ]
          });
  
          Ext.getWin().on('beforeunload', me.onUnload, me);
  
          me.isReady = true;
          me.fireEvent('ready', me);
      },
  
      /**
       * This method returns the configuration object for the Desktop object. A derived
       * class can override this method, call the base version to build the config and
       * then modify the returned object before returning it.
       */
      getDesktopConfig: function () {
          var me = this, cfg = {
              app: me,
              taskbarConfig: me.getTaskbarConfig()
          };
  
          Ext.apply(cfg, me.desktopConfig);
          return cfg;
      },
  
      getModules: Ext.emptyFn,
  
      /**
       * This method returns the configuration object for the Start Button. A derived
       * class can override this method, call the base version to build the config and
       * then modify the returned object before returning it.
       */
      getStartConfig: function () {
          var me = this,
              cfg = {
                  app: me,
                  menu: []
              },
              launcher;
  
          Ext.apply(cfg, me.startConfig);
  
          Ext.each(me.modules, function (module) {
              launcher = module.launcher;
              if (launcher) {
                  launcher.handler = launcher.handler || Ext.bind(me.createWindow, me, [module]);
                  cfg.menu.push(module.launcher);
              }
          });
  
          return cfg;
      },
  
      createWindow: function(module) {
          var window = module.createWindow();
          window.show();
      },
  
      /**
       * This method returns the configuration object for the TaskBar. A derived class
       * can override this method, call the base version to build the config and then
       * modify the returned object before returning it.
       */
      getTaskbarConfig: function () {
          var me = this, cfg = {
              app: me,
              startConfig: me.getStartConfig()
          };
  
          Ext.apply(cfg, me.taskbarConfig);
          return cfg;
      },
  
      initModules : function(modules) {
          var me = this;
          Ext.each(modules, function (module) {
              module.app = me;
          });
      },
  
      getModule : function(name) {
      	var ms = this.modules;
          for (var i = 0, len = ms.length; i < len; i++) {
              var m = ms[i];
              if (m.id == name || m.appType == name) {
                  return m;
              }
          }
          return null;
      },
  
      onReady : function(fn, scope) {
          if (this.isReady) {
              fn.call(scope, this);
          } else {
              this.on({
                  ready: fn,
                  scope: scope,
                  single: true
              });
          }
      },
  
      getDesktop : function() {
          return this.desktop;
      },
  
      onUnload : function(e) {
          if (this.fireEvent('beforeunload', this) === false) {
              e.stopEvent();
          }
      }
  });
  