text: Ext.define('KitchenSink.controller.Main', {
      extend: 'Ext.app.Controller',
      requires: [
          'KitchenSink.view.*',
          'Ext.window.Window'
      ],
  
      stores: [
          'Companies',
          'Restaurants',
          'Files',
          'States',
          'BigData'
      ],
  
      refs: [
          {
              ref: 'viewport',
              selector: 'viewport'
          },
          {
              ref: 'navigation',
              selector: 'navigation'
          },
          {
              ref: 'contentPanel',
              selector: 'contentPanel'
          },
          {
              ref: 'descriptionPanel',
              selector: 'descriptionPanel'
          },
          {
              ref: 'codePreview',
              selector: 'codePreview'
          }
      ],
  
      exampleRe: /^\s*\/\/\s*(\<\/?example>)\s*$/,
  
      init: function() {
          this.control({
              'navigation': {
                  selectionchange: 'onNavSelectionChange'
              },
              'viewport': {
                  afterlayout: 'afterViewportLayout'
              },
              'codePreview tool[type=maximize]': {
                  click: 'onMaximizeClick'
              },
              'contentPanel': {
                  resize: 'centerContent'
              },
              'tool[regionTool]': {
                  click: 'onSetRegion'
              }
          });
      },
              
      onSetRegion: function (tool) {
          var panel = tool.toolOwner;
  
          var regionMenu = panel.regionMenu || (panel.regionMenu =
                  Ext.widget({
                      xtype: 'menu',
                      items: [{
                          text: 'North',
                          checked: panel.region === 'north',
                          group: 'mainregion',
                          handler: function () {
                              panel.setBorderRegion('north');
                          }
                      },{
                          text: 'South',
                          checked: panel.region === 'south',
                          group: 'mainregion',
                          handler: function () {
                              panel.setBorderRegion('south');
                          }
                      },{
                          text: 'East',
                          checked: panel.region === 'east',
                          group: 'mainregion',
                          handler: function () {
                              panel.setBorderRegion('east');
                          }
                      },{
                          text: 'West',
                          checked: panel.region === 'west',
                          group: 'mainregion',
                          handler: function () {
                              panel.setBorderRegion('west');
                          }
                      }]
                  }));
  
          regionMenu.showBy(tool.el);
      },
  
      afterViewportLayout: function() {
          if (!this.navigationSelected) {
              var id = location.hash.substring(1),
                  navigation = this.getNavigation(),
                  store = navigation.getStore(),
                  node;
  
              node = id ? store.getNodeById(id) : store.getRootNode().firstChild.firstChild;
  
              navigation.getSelectionModel().select(node);
              navigation.getView().focusNode(node);
              this.navigationSelected = true;
          }
      },
  
      onNavSelectionChange: function(selModel, records) {
          var record = records[0],
              text = record.get('text'),
              xtype = record.get('id'),
              alias = 'widget.' + xtype,
              contentPanel = this.getContentPanel(),
              themeName = Ext.themeName,
              cmp;
  
          if (xtype) { // only leaf nodes have ids
              contentPanel.removeAll(true);
  
              var className = Ext.ClassManager.getNameByAlias(alias);
              var ViewClass = Ext.ClassManager.get(className);
              var clsProto = ViewClass.prototype;
              if (clsProto.themes) {
                  clsProto.themeInfo = clsProto.themes[themeName];
                  if (themeName === 'gray' || themeName === 'access') {
                      clsProto.themeInfo = Ext.applyIf(clsProto.themeInfo || {}, clsProto.themes.classic);
                  }
              }
  
              cmp = new ViewClass();
              contentPanel.add(cmp);
              if (cmp.floating) {
                  cmp.show();
              } else {
                  this.centerContent();
              }
  
              contentPanel.setTitle(text);
  
              document.title = document.title.split(' - ')[0] + ' - ' + text;
              location.hash = xtype;
  
              this.updateDescription(clsProto);
  
              if (clsProto.exampleCode) {
                  this.updateCodePreview(clsProto.exampleCode);
              } else {
                  this.updateCodePreviewAsync(clsProto, xtype);
              }
          }
      },
  
      onMaximizeClick: function(){
          var preview = this.getCodePreview(),
              code = preview.getEl().down('.prettyprint').dom.innerHTML;
  
          var w = new Ext.window.Window({
              rtl: false,
              baseCls: 'x-panel',
              maximized: true,
              title: 'Code Preview',
              plain: true,
              cls: 'preview-container',
              autoScroll: true,
              bodyStyle: 'background-color:white',
              html: '<pre class="prettyprint">' + code + '</pre>',
              closable: false,
              tools: [{
                  type: 'close',
                  handler: function() {
                      w.hide(preview, function() {
                          w.destroy();
                      });
                  }
              }]
          });
          w.show(preview);
      },
  
      processCodePreview: function (clsProto, text) {
          var me = this,
              lines = text.split('\n'),
              removing = false,
              keepLines = [],
              tempLines = [],
              n = lines.length,
              i, line;
  
          // Remove all "example" blocks as they are fluff.
          //
          for (i = 0; i < n; ++i) {
              line = lines[i];
              if (removing) {
                  if (me.exampleRe.test(line)) {
                      removing = false;
                  }
              } else if (me.exampleRe.test(line)) {
                  removing = true;
              } else {
                  tempLines.push(line);
              }
          }
  
          // Inline any themeInfo values to clarify the code.
          //
          if (clsProto.themeInfo) {
              var path = ['this', 'themeInfo'];
  
              function process (obj) {
                  for (var name in obj) {
                      var value = obj[name];
  
                      path.push(name);
  
                      if (Ext.isPrimitive(value)) {
                          if (Ext.isString(value)) {
                              value = "'" + value + "'";
                          }
                          me.replaceValues(tempLines, path.join('.'), value);
                      } else {
                          process(value);
                      }
  
                      path.pop();
                  }
              }
  
              process(clsProto.themeInfo);
          }
  
          // Remove any lines with remaining (unused) themeInfo. These properties will
          // be "undefined" for this theme and so are useless to the example.
          //
          for (i = 0, n = tempLines.length; i < n; ++i) {
              line = tempLines[i];
              if (line.indexOf('themeInfo') < 0) {
                  keepLines.push(line);
              }
          }
  
          var code = keepLines.join('\n');
          code = Ext.htmlEncode(code);
          clsProto.exampleCode = code;
      },
  
      replaceValues: function (lines, text, value) {
          var n = lines.length,
              i, pos, line;
  
          for (i = 0; i < n; ++i) {
              line = lines[i];
              pos = line.indexOf(text);
              if (pos >= 0) {
                  lines[i] = line.split(text).join(String(value));
              }
          }
      },
  
      updateCodePreview: function (text) {
          this.getCodePreview().update(
              '<pre id="code-preview-container" class="prettyprint">' + text + '</pre>'
          );
          prettyPrint();
      },
  
      updateCodePreviewAsync: function(clsProto, xtype) {
          var me = this,
              className = Ext.ClassManager.getNameByAlias('widget.' + xtype),
              path = className.replace(/\./g, '/').replace('KitchenSink', 'app') + '.js';
  
          if (!Ext.repoDevMode) {
              path = '../../../kitchensink/' + path;
          }
  
          Ext.Ajax.request({
              url: path,
              success: function(response) {
                  me.processCodePreview(clsProto, response.responseText);
                  me.updateCodePreview(clsProto.exampleCode);
              }
          });
      },
  
      updateDescription: function (clsProto) {
          var description = clsProto.exampleDescription,
              descriptionPanel = this.getDescriptionPanel();
  
          if (Ext.isArray(description)) {
              clsProto.exampleDescription = description = description.join('');
          }
  
          descriptionPanel.update(description);
      },
  
      centerContent: function() {
          var contentPanel = this.getContentPanel(),
              body = contentPanel.body,
              item = contentPanel.items.getAt(0),
              align = 'c-c',
              overflowX,
              overflowY,
              offsets;
  
          if (item) {
              overflowX = (body.getWidth() < (item.getWidth() + 40));
              overflowY = (body.getHeight() < (item.getHeight() + 40));
  
              if (overflowX && overflowY) {
                  align = 'tl-tl';
                  offsets = [20, 20];
              } else if (overflowX) {
                  align = 'l-l';
                  offsets = [20, 0];
              } else if (overflowY) {
                  align = 't-t';
                  offsets = [0, 20];
              }
  
              item.alignTo(contentPanel.body, align, offsets);
          }
      }
  });
  