Ext.ns('iceCapXml');

iceCapXml.changePending = false;
iceCapXml.count = 0;

// -----------------------------------------------------------------------
// Override extjs
// -----------------------------------------------------------------------

Ext.override(Ext.grid.GridView,{
  getCell : function(rowIndex, colIndex){
    var row = this.getRow(rowIndex);
    if (typeof (row) == 'undefined') {
      return false;
    } else {
      return row.getElementsByTagName('td')[colIndex];
    }
  }
});

// -----------------------------------------------------------------------
// Panel setting
// -----------------------------------------------------------------------

iceCapXml.panelSetting = Ext.extend(Ext.Panel, {
  initComponent:function() {
    var me = this;

    Ext.apply(this, {
      layout:'border'
      ,cls:'viewport'
      ,border:false
      ,items:[
        {
          region:'west'
          ,layout:'form'
          ,bodyStyle:'padding:5px'
          ,border:true
          ,title:menu.I18N['method']
          ,width:230
          ,collapsible:true
          ,split:true
          ,collapseMode:'mini'
          ,bodyStyle:'overflow-y:auto;overflow-x:hidden;'
          ,buttons:[
            {
              text:menu.I18N['save']
              ,handler:function() {
                me.save();
              }
            },{
              text:menu.I18N['cancel']
              ,handler:function() {
                me.cancel();
              }
            }
          ]
        },{
          region:'center'
          ,border:true
          ,title:menu.I18N['properties']
          ,html:'<div id="form_body"></div>'
          ,bodyStyle:'overflow-y:auto;overflow-x:hidden;'
        },{
          region:'east'
          ,xtype:'panel'
          ,title:menu.I18N['help']
          ,border:false
          ,width:240
          ,collapsible:true
          ,split:true
          ,collapseMode:'mini'
          ,items: {
            html:'<iframe id="help-content" src="/menu/help/emulator xml documentation('+me.language+').html" width="100%" height="100%" border="0" style="border:none;"></iframe>'
          }
          ,listeners: {
            afterLayout:function (region) {
              if (Ext.isIE) {
                var iframe = document.getElementById('help-content');
                if (iframe != null) {
                  var size = region.getSize();
                  iframe.height = size.height - 25;
                }
              }
            }
            ,resize:function (region) {
              if (Ext.isIE) {
                var iframe = document.getElementById('help-content');
                if (iframe != null) {
                  var size = region.getSize();
                  iframe.height = size.height - 25;
                }
              }
            }
            ,updateHelp: function (link) {
              if (document.getElementById('help-content')) {
                document.getElementById('help-content').src = '/menu/help/emulator xml documentation('+me.language+').html#'+link;
              }
            }
          }
        }
      ]
    });
    iceCapXml.panelSetting.superclass.initComponent.call(this);

		this.addEvents(
				/**
					* @event jsonReady
					* Fires when converting xml document to json object is ready
					* @param {Ext.Panel} this
					* @param {Object} json
					*/
				'jsonReady'
        ,'afterSave'
		);

    this.on('jsonReady', function(json) {
        this.childComponents(json);
    }, this);
    this.on('afterSave', function() {
    }, this);

    Ext.Ajax.request({
      url:'/menu/iceCapXmlS.aspx.xml?action=get&xmlDoc=' + this.xmlDoc + '&xmlHive=' + this.xmlHive + '&token=' + this.token
      ,success: function ( result, request ) {
        iceCapXml.xml2json(me, result.responseXML);
      }
    });
  },
  childComponents:function(json) {
    this.json = json;
    if (typeof(this.ownerCt) != 'undefind' && typeof(this.ownerCt.setTitle) == 'function') {
      this.ownerCt.setTitle(menu.I18N['setting'] + ': "' + json.id + '"');
    }

    var obj = {};
    obj.xtype  = 'iceCapXml.recognitionGrid';
    obj.parent = this.layout;
    obj.parentJson = json.select;
    obj.json       = json.select.when;
    this.layout.west.panel.add(obj);

    var obj = {};
    obj.xtype  = 'iceCapXml.propertyGrid';
    obj.parent = this.layout;
    obj.parentJson = json.areas;
    obj.json       = json.areas.property;
    this.layout.west.panel.add(obj);

    var obj = {};
    obj.xtype  = 'iceCapXml.keysGrid';
    obj.parent = this.layout;
    obj.parentJson = json.keys;
    obj.json       = json.keys.item;
    this.layout.west.panel.add(obj);

    this.doLayout();
  },
  cancel:function() {
    if (iceCapXml.changePending) {
      Ext.Msg.show({
        title:menu.I18N['saveChanges']
        ,msg:menu.I18N['saveYesNo']
        ,buttons: Ext.Msg.YESNO
        ,fn: this.cancelBtn
        ,scope:this
        ,icon: Ext.MessageBox.QUESTION
      });      
    } else {
      this.close();
    }
  },
  cancelBtn:function(btn) {
    if (btn == 'yes') { 
      this.save();
    } else {
      this.close();
    }
    iceCapXml.changePending = false;
  },
  save:function() {
    var options = {}
    options.rootTagName = 'panel';
    options.replace = [{'areas.property.menu.item.option':'id'},{'areas.property.toolbar.buttons.item.button':'id'},{'keys.item.key':'id'}];
    options.ignore = ['select.when.type','select.when.id','areas.property.id','areas.property.attributes','areas.property.menu.item.id','areas.property.column.item.id','areas.property.toolbar.buttons.item.id','areas.property.toolbar.fields.item.id','keys.item.id','keys.item.type'];
    Ext.Ajax.request({
      url:'/menu/iceCapXmlS.aspx.xml?action=save&xmlDoc=' + this.xmlDoc + '&xmlHive=' + this.xmlHive + '&token=' + this.token
      ,xmlData: json2xml.convert(this.json, options)
      ,success: function () {
        this.fireEvent('afterSave');
        this.close();
      }
      ,scope:this
    });
  },
  close:function() {
    if (typeof(this.ownerCt) != 'undefind' && typeof(this.ownerCt.close) == 'function') {
      this.ownerCt.close();
    }
  }
});
Ext.reg('iceCapXml.panelSetting', iceCapXml.panelSetting);

// -----------------------------------------------------------------------
// Panel recognition Grid
// -----------------------------------------------------------------------

iceCapXml.recognitionGrid = Ext.extend(Ext.grid.GridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'line'}
        ,{name:'column'}
        ,{name:'length'}
        ,{name:'equal'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      dataType: 'select'
      ,title:menu.I18N['panelRecognition']
      ,store: store
      ,json:this.json
      ,columns:[
        {header: menu.I18N['line'], width:32, sortable:false, dataIndex: 'line'}
        ,{header: menu.I18N['column'], width:32, sortable:false, dataIndex: 'column'}
        ,{header: menu.I18N['valueLength'], width:32, sortable:false, dataIndex: 'length'}
        ,{header: menu.I18N['equal'], width:152, sortable:false, dataIndex: 'equal'}
      ]
      ,sm: new Ext.grid.RowSelectionModel({singleSelect:true})
      ,loadMask:false
      ,autoHeight:true
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'recognitionGrid'
    });
    iceCapXml.recognitionGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'edit',text: menu.I18N['edit'],cls:'mnu-icon-edit smd-default',handler:this.onRowRightClick,scope:this}
        ,{id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
    this.on('rowclick', function(grid, rowIndex, e) {
      this.editRow('edit');
    },this);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop:function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.recognitionGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().selectRow(rowIndex);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'edit':
      this.editRow('edit');
      break;
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.editRow('add');
      break;
    }
  },
  editRow:function(func) {
    var items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['line'],name:'line',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['column'],name:'column',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['valueLength'],name:'length',allowBlank:false}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['equal'],name:'equal',allowBlank:false, width:400}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,labelWidth:40
      ,property:'recognition'
      ,helpId:'recognition'
    });
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.recognitionGrid', iceCapXml.recognitionGrid);

// -----------------------------------------------------------------------
// Property Grid (Areas to convert)
// -----------------------------------------------------------------------

iceCapXml.propertyGrid = Ext.extend(Ext.grid.GridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'type'}
        ,{name:'xPosition', type:'int', mapping:'attributes.xPosition'}
        ,{name:'yPosition', type:'int', mapping:'attributes.yPosition'}
        ,{name:'startLine', type:'int', mapping:'attributes.startLine'}
        ,{name:'endLine', type:'int', mapping:'attributes.endLine'}
      ]
      ,data:this.json
    });
    var addMenu = new Ext.menu.Menu({
      items:[
        {
          id:'input'
          ,text:'Input field'
          ,handler:this.onToolbarClick
          ,iconCls:'iceCap-icon-inputField'
          ,scope:this
        },{
          id:'output'
          ,text:'Output field'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-outputField'
        },{
          id:'label'
          ,text:'Label'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-label'
        },{
          id:'area2grid'
          ,text:'Area to grid'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-grid'
        },{
          id:'area2columns'
          ,text:'Area to columns'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-column'
        },{
          id:'area2panel'
          ,text:'Area to panel'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-panel'
        },{
          id:'area2commandLine'
          ,text:'Area to command line'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-commandLine'
        },{
          id:'ignoreArea'
          ,text:'Ignore area'
          ,handler:this.onToolbarClick
          ,scope:this
          ,iconCls:'iceCap-icon-ignoreArea'
        }
      ]
    });
    Ext.apply(this, {
      dataType: 'areas'
      ,parent:this.parent
      ,title:menu.I18N['panelAreas']
      ,store: store
      ,columns:[
        {header: menu.I18N['method'], width:78, sortable:false, dataIndex: 'type'}
        ,{header: menu.I18N['x'], width:32, sortable:false, dataIndex: 'xPosition'}
        ,{header: menu.I18N['y'], width:32, sortable:false, dataIndex: 'yPosition'}
        ,{header: menu.I18N['start'], width:32, sortable:false, dataIndex: 'startLine'}
        ,{header: menu.I18N['end'], width:32, sortable:false, dataIndex: 'endLine'}
      ]
      ,sm: new Ext.grid.RowSelectionModel({singleSelect:true})
      ,loadMask:false
      ,autoHeight:true
	    ,tbar: [
        {
          id:'property_add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,menu:addMenu
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'propertyGrid'
    });
    iceCapXml.propertyGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'edit',text: menu.I18N['edit'],cls:'mnu-icon-edit smd-default',handler:this.onRowRightClick,scope:this}
        ,{id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
    this.on('rowclick', function(grid, rowIndex, e) {
        row = this.getSelectionModel().getSelected();
        this.editRow('edit', row);
    },this);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.propertyGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().selectRow(rowIndex);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'edit':
      row = this.getSelectionModel().getSelected();
      this.editRow('edit', row);
      break;
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    var row = {};
    row.data = {};
    row.data.type = btn.id
    this.editRow('add',row);
  },
  editRow:function(func, row) {
    switch(row.data.type) {
    case 'input' :
      this.inputFieldForm(func);
      break;
    case 'output' :
      this.outputFieldForm(func);
      break;
    case 'label' :
      this.labelForm(func);
      break;
    case 'area2grid' :
      this.area2gridForm(func);
      break;
    case 'area2columns' :
      this.area2columnsForm(func);
      break;
    case 'area2panel' :
      this.area2panelForm(func);
      break;
    case 'area2commandLine' :
      this.area2commandLineForm(func);
      break;
    case 'ignoreArea' :
      this.ignoreAreaForm(func);
      break;
    }
  },
  inputFieldForm:function(func) {
    items = [
      {xtype:'iceCapXml.dataTypeCombo'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['line'],name:'line',allowBlank:false}
      ,{xtype:'iceCapXml.regionCombo'}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['name'],name:'name',width:100}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['label'],name:'label',width:200}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['labelWidth'],name:'labelWidth'}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['labelSeparator'],name:'labelSeparator'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['maxLength'],name:'maxLength'}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'input'
      ,helpId:'input'
    });
  },
  outputFieldForm:function(func) {
    items = [
      {xtype:'iceCapXml.dataTypeCombo'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['line'],name:'line',allowBlank:false}
      ,{xtype:'iceCapXml.regionCombo'}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['name'],name:'name',width:100}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['label'],name:'label',width:200}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['labelWidth'],name:'labelWidth'}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['labelSeparator'],name:'labelSeparator'}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'output'
      ,helpId:'output'
    });
  },
  labelForm:function(func) {
    items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['line'],name:'line',allowBlank:false}
      ,iceCapXml.regionCombo
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'label'
      ,helpId:'label'
    });
  },
  area2gridForm:function(func) {
    // set form values from json
    var gridData = {};
    if (func != 'add') {
      row = this.getSelectionModel().getSelected();
      jsonIndex = iceCapXml.findJsonIndex(this.json, row.data.id);
      gridData = this.json[jsonIndex];
    }

    if (typeof (gridData.type)                 == 'undefined') gridData.type                 = 'area2grid';
    if (typeof (gridData.column)               == 'undefined') gridData.column               = {};
    if (typeof (gridData.column.item)          == 'undefined') gridData.column.item          = [];
    if (typeof (gridData.data)                 == 'undefined') gridData.data                 = {};
    if (typeof (gridData.menu)                 == 'undefined') gridData.menu                 = {};
    if (typeof (gridData.menu.item)            == 'undefined') gridData.menu.item            = [];
    if (typeof (gridData.quickOption)          == 'undefined') gridData.quickOption          = {};
    if (typeof (gridData.toolbar)              == 'undefined') gridData.toolbar              = {};
    if (typeof (gridData.toolbar.buttons)      == 'undefined') gridData.toolbar.buttons      = {};
    if (typeof (gridData.toolbar.buttons.item) == 'undefined') gridData.toolbar.buttons.item = [];
    if (typeof (gridData.toolbar.fields)       == 'undefined') gridData.toolbar.fields       = {};
    if (typeof (gridData.toolbar.fields.item)  == 'undefined') gridData.toolbar.fields.item  = [];
    
    var items = [
      iceCapXml.columns(
        [
          {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['x-position'],name:'xPosition',columnNumber:0}
          ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['y-position'],name:'yPosition',columnNumber:1}
        ]
        ,[57,57]
        ,[127,127]
      )
      ,{xtype:'fieldset',title:menu.I18N['rightClickMenu'],height:315,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:false,collapsible:true,autoScroll:true
        ,items:[
          {xtype:'iceCapXml.rightClickMenuForm',json:gridData.menu}
        ]
      }
      ,{xtype:'fieldset',title:menu.I18N['columns'],height:345,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:true,collapsible:true,autoScroll:true
        ,listeners:{
          expand:function(fs) {
            iceCapXml.setAutoExpandColumnWidth(fs);
          }
        }
        ,items:[
          {xtype:'iceCapXml.gridColumnForm',json:gridData.column}
        ]
      }
      ,{xtype:'fieldset',title:menu.I18N['quickOption'],height:50,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:true,collapsible:true,autoScroll:true
        ,items:[
          {xtype:'iceCapXml.quickOptionForm',json:gridData.quickOption}
        ]
      }
      ,{xtype:'fieldset',title:menu.I18N['data'],height:70,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:true,collapsible:true,autoScroll:true
        ,items:[
          {xtype:'iceCapXml.gridDataForm',json:gridData.data}
        ]
      }
      ,{xtype:'fieldset',title:menu.I18N['toolbar'],height:265,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:true,collapsible:true,autoScroll:true
        ,items:[
          {xtype:'fieldset',title:menu.I18N['toolbarButtons'],autoHeight:true,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:false,collapsible:true,autoScroll:true
            ,listeners:{
              expand:function(fs) {
                iceCapXml.setAutoExpandColumnWidth(fs);
              }
            }
            ,items:[
              {xtype:'iceCapXml.gridToolbarButtonsGrid',json:gridData.toolbar.buttons.item}
            ]
          }
          ,{xtype:'fieldset',title:menu.I18N['toolbarFields'],autoHeight:true,autoWidth:true,style:'margin-bottom:2px;padding:6px 0 0 8px;',hideBorders:true,collapsed:true,collapsible:true,autoScroll:true
            ,listeners:{
              expand:function(fs) {
                iceCapXml.setAutoExpandColumnWidth(fs);
              }
            }
            ,items:[
              {xtype:'iceCapXml.gridToolbarFieldsGrid',json:gridData.toolbar.fields.item}
            ]
          }
        ]
      }
    ];
    var panel = new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'area2grid'
      ,helpId:'area2grid'
    });
  },
  area2columnsForm:function(func) {
    var checked = (this.json.removeLabelDots == 'true') ? true : false;
    items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['x-position'],name:'xPosition'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['y-position'],name:'yPosition'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'startLine',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startColumnNumber'],name:'startColumn',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'endLine',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endColumnNumber'],name:'endColumn',allowBlank:false}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['columnWidth'],name:'columnWidth',width:300}
      ,{xtype:'iceCapXml.checkBox',fieldLabel:menu.I18N['removeLabelDots'],name:'removeLabelDots',inputValue:'true',checked:checked}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'area2columns'
      ,helpId:'area2columns'
    });
  },
  area2panelForm:function(func) {
    items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['x-position'],name:'xPosition'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['y-position'],name:'yPosition'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'startLine',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startColumnNumber'],name:'startColumn',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'endLine',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endColumnNumber'],name:'endColumn',allowBlank:false}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'area2panel'
      ,helpId:'area2panel'
    });
  },
  area2commandLineForm:function(func) {
    var checked = (this.json.collapsible == 'true') ? true : false;
    items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['commandLine'],name:'commandLine'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['titleLine'],name:'titleLine'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['titleColumn'],name:'titleColumn',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['titleLength'],name:'titleLength',allowBlank:false}
      ,{xtype:'iceCapXml.checkBox',fieldLabel:menu.I18N['collapsible'],name:'collapsible',inputValue:'true',checked:checked}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'area2commandLine'
      ,helpId:'area2commandLine'
    });
  },
  ignoreAreaForm:function(func) {
    items = [
      {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'startLine',allowBlank:false,help:'startLine'}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startColumnNumber'],name:'startColumn',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'endLine',allowBlank:false}
      ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endColumnNumber'],name:'endColumn',allowBlank:false}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,property:'ignoreArea'
      ,helpId:'ignoreArea'
    });
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.propertyGrid', iceCapXml.propertyGrid);

// -----------------------------------------------------------------------
// Keys
// -----------------------------------------------------------------------

iceCapXml.keysGrid = Ext.extend(Ext.grid.GridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'key'}
        ,{name:'text'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      dataType: 'keys'
      ,title:menu.I18N['functionKeys']
      ,store: store
      ,columns:[
        {header: menu.I18N['key'], width:32, sortable:false, dataIndex: 'key'}
        ,{header: menu.I18N['text'], width:216, sortable:false, dataIndex: 'text'}
      ]
      ,sm: new Ext.grid.RowSelectionModel({singleSelect:true})
      ,loadMask:false
      ,autoHeight:true
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        },{
          id:'properties'
          ,text: menu.I18N['properties']
          ,tooltip: menu.I18N['properties']
          ,cls:'x-btn-text-icon mnu-tb-properties'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'keysGrid'
    });
    iceCapXml.keysGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'edit',text: menu.I18N['edit'],cls:'mnu-icon-edit smd-default',handler:this.onRowRightClick,scope:this}
        ,{id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
    this.on('rowclick', function(grid, rowIndex, e) {
      this.editRow('edit');
    },this);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.keysGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().selectRow(rowIndex);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'edit':
      this.editRow('edit');
      break;
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.editRow('add');
      break;
    case 'properties':
      this.editProperties();
      break;
    }
  },
  editRow:function(func) {
    var items = [
      {xtype:'iceCapXml.textField',fieldLabel:menu.I18N['functionkey'],name:'key',allowBlank:false}
      ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['text'],name:'text',width:300}
    ];
    new iceCapXml.propertiesForm({
      items:items
      ,grid:this
      ,func:func
      ,labelWidth:66
      ,property:'keys'
      ,helpId:'keys'
    });
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  },
  editProperties:function() {
    var grid = this;
    iceCapXml.resetPropertiesForm(grid);

    // set title
    var centerPanel = grid.parent.center;
    centerPanel.panel.setTitle(menu.I18N['properties'] + ': "' + menu.I18N['functionKeys'] + '"' );

    var frm = new Ext.form.FormPanel({
      id:'form_' + iceCapXml.count++
      ,labelAlign: 'left'
      ,buttonAlign: 'left'
      ,labelWidth:66
      ,border:false
      ,bodyStyle:'padding:5px 5px 0'
      ,layout:'form'
      ,helpId:'keyProperties'
      ,items:[
        {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'startLine',value:this.parentJson.startLine,allowBlank:false}
        ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'endLine',value:this.parentJson.endLine,allowBlank:false}
      ]
      ,buttons:[
        {
          text:'OK'
          ,handler:function() {
            this.saveProperties(frm);
          }
          ,scope:this
        },{
          text:menu.I18N['cancel']
          ,handler:function() {
            iceCapXml.resetPropertiesForm(grid);
          }
          ,scope:this
        }
      ]
    });
    frm.render('form_body');
    frm.getForm().findField('startLine').focus(true,10);
  },
  saveProperties:function(frm) {
    frm.items.each(function(field) {
      var value = field.getValue();
      if (value != field.orignalValue) {
        this.parentJson[field.name] = value;
        iceCapXml.changePending = true;
      }
    },this);
    iceCapXml.resetPropertiesForm(this);
  }
});
Ext.reg('iceCapXml.keysGrid', iceCapXml.keysGrid);

// -----------------------------------------------------------------------
// Menu (rightclick) Form
// -----------------------------------------------------------------------

iceCapXml.rightClickMenuForm = Ext.extend(Ext.Panel, {
  initComponent:function() {
    var fkeys = [];
    for (var i = 1; i < 25; i++) {
      var key = ['F'+i];
      fkeys.push(key);
    };
    Ext.apply(this, {
      id:'form_' + iceCapXml.count++
      ,labelAlign: 'left'
      ,labelWidth:100
      ,border:false
      ,bodyStyle:'padding:5px 5px 0'
      ,autoWidth:true
      ,layout:'form'
      ,helpId:'rightClickMenu'
      ,items:[
        iceCapXml.columns(
          [
            {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'menu.startLine',value:this.json.startLine,allowBlank:false,columnNumber:0}
            ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'menu.endLine',value:this.json.endLine,allowBlank:false,columnNumber:1}
            ,{xtype:'iceCapXml.comboBox'
              ,fieldLabel:menu.I18N['moreOptionKey']
              ,hiddenName: 'moreOptionKey'
              ,store: new Ext.data.SimpleStore({
                fields: ['key'],
                data : fkeys 
              })
              ,displayField: 'key'
              ,typeAhead: true
              ,mode: 'local'
              ,triggerAction: 'all'
              ,selectOnFocus:true
              ,value:this.json.moreOptionKey
              ,columnNumber:2
            }
          ]
          ,[50,50,95]
          ,[120,120,200]
        )
        ,{xtype:'iceCapXml.rightClickMenuGrid',json:this.json.item}
      ]
    });
    iceCapXml.rightClickMenuForm.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.rightClickMenuForm', iceCapXml.rightClickMenuForm);

// -----------------------------------------------------------------------
// Menu (rightclick) Grid
// -----------------------------------------------------------------------

iceCapXml.rightClickMenuGrid = Ext.extend(Ext.grid.EditorGridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'option'}
        ,{name:'text'}
        ,{name:'breakout'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      store: store
      ,columns:[
        {header: menu.I18N['option'], width:50, sortable:false, dataIndex:'option',editor:new iceCapXml.textField({name:'menu.option',hideLabel:true,helpId:'rightClickMenu'})}
        ,{header: menu.I18N['text'],id:'text',sortable:false, dataIndex:'text',editor:new iceCapXml.textField({name:'menu.text',hideLabel:true,helpId:'rightClickMenu'})}
        ,{header: menu.I18N['breakoutFunction'],id:'breakout',sortable:false, dataIndex:'breakout',editor:new iceCapXml.breakoutFunctionCombo({name:'menu.breakout',hideLabel:true,helpId:'rightClickMenu'})}
      ]
      ,autoExpandColumn:'breakout'
      ,width:462
      ,height:250
      ,clicksToEdit:1
      ,loadMask:false
      ,border:false
      ,sm:new iceCapXml.CellSelectionModelWithMultiRowSelect({
				addBottomRow: function(self) {}
			})
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'rightClickMenu'
      ,helpId:'rightClickMenu'
      ,type:'menu'
    });
    iceCapXml.rightClickMenuGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.rightClickMenuGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().clearSelections();
    var cell = [rowIndex,0];
    this.getSelectionModel().selectRow(cell);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.addRow('add');
      break;
    }
  },
  addRow:function(func) {
    var store = this.getStore();
    var row = new store.recordType();
    store.fields.each(function(field) {
      row.data[field.name] = field.defaultValue;
    });
    var rowIndex = store.data.items.length;
    row.data['id'] = rowIndex;

    store.add(row);
    this.startEditing(rowIndex, 0);

    this.json.splice(rowIndex,0,row.data);
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.rightClickMenuGrid', iceCapXml.rightClickMenuGrid);

// -----------------------------------------------------------------------
// Column Form
// -----------------------------------------------------------------------

iceCapXml.gridColumnForm = Ext.extend(Ext.Panel, {
  initComponent:function() {
    var checked = (this.json.showOptionField == 'true') ? true : false;
    Ext.apply(this, {
      id:'form_' + iceCapXml.count++
      ,labelAlign: 'left'
      ,labelWidth:100
      ,border:false
      ,bodyStyle:'padding:5px 5px 0'
      ,defaults:{
        width:50
      }
      ,autoWidth:true
      ,layout:'form'
      ,helpId:'gridColumn'
      ,items:[
        iceCapXml.columns(
          [
            {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'column.startLine',value:this.json.startLine,allowBlank:false,columnNumber:0}
            ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'column.endLine',value:this.json.endLine,allowBlank:false,columnNumber:1}
            ,{xtype:'iceCapXml.checkBox',fieldLabel:menu.I18N['showOptionField'],name:'column.showOptionField',inputValue:'true',checked:checked,value:this.json.showOptionField,columnNumber:2}
            ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['optionFieldColumn'],name:'column.optionFieldColumn',value:this.json.optionFieldColumn,columnNumber:0}
            ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['optionFieldLength'],name:'column.optionFieldLength',value:this.json.optionFieldLength,columnNumber:1}
          ]
          ,[90,90,90]
          ,[150,150,150]
        )
        ,{xtype:'iceCapXml.gridColumnGrid',json:this.json.item}
      ]
    });
    iceCapXml.gridColumnForm.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.gridColumnForm', iceCapXml.gridColumnForm);

// -----------------------------------------------------------------------
// Column Grid
// -----------------------------------------------------------------------

iceCapXml.gridColumnGrid = Ext.extend(Ext.grid.EditorGridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'header'}
        ,{name:'columnStart'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      store: store
      ,columns:[
        {header: menu.I18N['startColumnNumber'],width:50,sortable:false, dataIndex: 'columnStart',editor:new iceCapXml.numberField({name:'column.columnStart',hideLabel:true,helpId:'gridColumn'})}
        ,{header: menu.I18N['columnHeader'],id:'header', sortable:false, dataIndex: 'header',editor:new iceCapXml.textField({name:'column.header',hideLabel:true,helpId:'gridColumn'})}
      ]
      ,autoExpandColumn:'header'
      ,width:462
      ,height:224
      ,clicksToEdit:1
      ,loadMask:false
      ,border:false
      ,sm:new iceCapXml.CellSelectionModelWithMultiRowSelect({
				addBottomRow: function(self) {}
			})
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'gridColumn'
      ,helpId:'gridColumn'
      ,type:'column'
    });
    iceCapXml.gridColumnGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.gridColumnGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().clearSelections();
    var cell = [rowIndex,0];
    this.getSelectionModel().selectRow(cell);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.addRow('add');
      break;
    }
  },
  addRow:function(func) {
    var store = this.getStore();
    var row = new store.recordType();
    store.fields.each(function(field) {
      row.data[field.name] = field.defaultValue;
    });
    var rowIndex = store.data.items.length;
    row.data['id'] = rowIndex;

    store.add(row);
    this.startEditing(rowIndex, 0);

    this.json.splice(rowIndex,0,row.data);
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.gridColumnGrid', iceCapXml.gridColumnGrid);

// -----------------------------------------------------------------------
// Quick option Form
// -----------------------------------------------------------------------

iceCapXml.quickOptionForm = Ext.extend(Ext.Panel, {
  initComponent:function() {
    Ext.apply(this, {
      id:'form_' + iceCapXml.count++
      ,labelAlign: 'left'
      ,labelWidth:100
      ,border:false
      ,bodyStyle:'padding:5px 5px 0'
      ,defaults:{
        width:50
      }
      ,autoWidth:true
      ,layout:'form'
      ,helpId:'quickOption'
      ,items:[
        {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['line'],name:'quickOption.line',value:this.json.line}
      ]
    });
    iceCapXml.quickOptionForm.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.quickOptionForm', iceCapXml.quickOptionForm);

// -----------------------------------------------------------------------
// Data Form
// -----------------------------------------------------------------------

iceCapXml.gridDataForm = Ext.extend(Ext.Panel, {
  initComponent:function() {
    var checked = (this.json.showOptionField == 'true') ? true : false;
    Ext.apply(this, {
      id:'form_' + iceCapXml.count++
      ,labelAlign: 'left'
      ,labelWidth:100
      ,border:false
      ,bodyStyle:'padding:5px 5px 0'
      ,defaults:{
        width:50
      }
      ,autoWidth:true
      ,layout:'form'
      ,helpId:'gridData'
      ,items:[
        iceCapXml.columns(
          [
            {xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['startLineNumber'],name:'data.startLine',value:this.json.startLine,allowBlank:false,columnNumber:0}
            ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['endLineNumber'],name:'data.endLine',value:this.json.endLine,allowBlank:false,columnNumber:0}
            ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['subfileEndLine'],name:'data.subfileEndLine',value:this.json.subfileEndLine,allowBlank:false,columnNumber:1}
            ,{xtype:'iceCapXml.numberField',fieldLabel:menu.I18N['subfileEndColumn'],name:'data.subfileEndColumn',value:this.json.subfileEndColumn,allowBlank:false,columnNumber:1}
            ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['subfileMoreText'],name:'data.subfileMoreText',value:this.json.subfileMoreText,columnNumber:2}
            ,{xtype:'iceCapXml.textField',fieldLabel:menu.I18N['subfileBottomText'],name:'data.subfileBottomText',value:this.json.subfileBottomText,columnNumber:2}
          ]
          ,[50,104,100]
          ,[116,174,170]
        )
      ]
    });
    iceCapXml.gridDataForm.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.gridDataForm', iceCapXml.gridDataForm);

// -----------------------------------------------------------------------
// Toolbar Buttons Grid
// -----------------------------------------------------------------------

iceCapXml.gridToolbarButtonsGrid = Ext.extend(Ext.grid.EditorGridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'button'}
        ,{name:'text'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      store: store
      ,columns:[
        {header: menu.I18N['button'], width:50, sortable:false, dataIndex: 'button',editor:new iceCapXml.textField({name:'toolbar.buttons.button',hideLabel:true,helpId:'gridToolbarButtons'})}
        ,{header: menu.I18N['text'],id:'button_text',sortable:false, dataIndex: 'text',editor:new iceCapXml.textField({name:'toolbar.buttons.text',hideLabel:true,helpId:'gridToolbarButtons'})}
      ]
      ,autoExpandColumn:'button_text'
      ,width:440
      ,height:150
      ,clicksToEdit:1
      ,loadMask:false
      ,border:false
      ,sm:new iceCapXml.CellSelectionModelWithMultiRowSelect({
				addBottomRow: function(self) {}
			})
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'gridToolbarButtons'
      ,helpId:'gridToolbarButtons'
      ,type:'toolbar'
      ,subType:'buttons'
    });
    iceCapXml.gridToolbarButtonsGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.gridToolbarButtonsGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().clearSelections();
    var cell = [rowIndex,0];
    this.getSelectionModel().selectRow(cell);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.addRow('add');
      break;
    }
  },
  addRow:function(func) {
    var store = this.getStore();
    var row = new store.recordType();
    store.fields.each(function(field) {
      row.data[field.name] = field.defaultValue;
    });
    var rowIndex = store.data.items.length;
    row.data['id'] = rowIndex;

    store.add(row);
    this.startEditing(rowIndex, 0);

    this.json.splice(rowIndex,0,row.data);
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.gridToolbarButtonsGrid', iceCapXml.gridToolbarButtonsGrid);

// -----------------------------------------------------------------------
// Toolbar Fields Grid
// -----------------------------------------------------------------------

iceCapXml.gridToolbarFieldsGrid = Ext.extend(Ext.grid.EditorGridPanel, {
  initComponent:function() {
    var store = new Ext.data.JsonStore({
      fields:[
        {name:'id'}
        ,{name:'type'}
        ,{name:'line'}
        ,{name:'label'}
        ,{name:'contentLocation'}
      ]
      ,data:this.json
    });
    Ext.apply(this, {
      store: store
      ,columns:[
        {header: menu.I18N['type'],width:120, sortable:false, dataIndex: 'type',editor:new iceCapXml.inputTypeCombo({name:'toolbar.fields.type',hideLabel:true,helpId:'gridToolbarFields'})}
        ,{header: menu.I18N['line'],width:24,sortable:false, dataIndex: 'line',editor:new iceCapXml.textField({name:'toolbar.fields.line',hideLabel:true,helpId:'gridToolbarFields'})}
        ,{header: menu.I18N['contentLocation'],width:44,sortable:false, dataIndex: 'contentLocation',editor:new iceCapXml.regionCombo({name:'toolbar.fields.contentLocation',hideLabel:true,helpId:'gridToolbarFields'})}
        ,{header: menu.I18N['label'],id:'label',sortable:false, dataIndex: 'label',editor:new iceCapXml.textField({name:'toolbar.fields.label',hideLabel:true,helpId:'gridToolbarFields'})}
      ]
      ,autoExpandColumn:'label'
      ,width:440
      ,height:150
      ,clicksToEdit:1
      ,loadMask:false
      ,border:false
      ,sm:new iceCapXml.CellSelectionModelWithMultiRowSelect({
				addBottomRow: function(self) {}
			})
	    ,tbar: [
        {
          id:'add'
          ,text: menu.I18N['addNew']
          ,tooltip: menu.I18N['addNew']
          ,cls:'x-btn-text-icon mnu-tb-add'
          ,handler: this.onToolbarClick
          ,scope:this
        }
	    ]
      ,enableDragDrop: true
      ,ddGroup:'gridToolbarFields'
      ,helpId:'gridToolbarFields'
      ,type:'toolbar'
      ,subType:'fields'
    });
    iceCapXml.gridToolbarFieldsGrid.superclass.initComponent.call(this);

    this.on('rowcontextmenu', this.onRowMenu);
    this.rowMenu = new Ext.menu.Menu({
      id: 'rowMenu'
      ,items: [
        {id:'delete',text: menu.I18N['delete'],cls:'mnu-icon-delete',handler:this.onRowRightClick,scope:this}
      ]
    });

    this.on('rowcontextmenu', this.onRowMenu);
  },
  afterRender:function() {
    var dropTargetEl =  this.getView().el.dom.childNodes[0].childNodes[1];
	  new Ext.dd.DropTarget(dropTargetEl, {
      ddGroup:this.ddGroup
      ,copy:true
      ,notifyDrop : function(ddSource, e, data) {
        iceCapXml.gridDragAndDrop(ddSource, e, data);
      }
    }); 	
    iceCapXml.gridToolbarFieldsGrid.superclass.afterRender.call(this);
  },
  onRowMenu:function(grid, rowIndex, e) {
    e.stopEvent();
    this.getSelectionModel().clearSelections();
    var cell = [rowIndex,0];
    this.getSelectionModel().selectRow(cell);
    var coords = e.getXY();
    this.rowMenu.showAt([coords[0], coords[1]]);
  },
  onRowRightClick:function(item) {
    switch (item.id) {
    case 'delete':
      Ext.Msg.show({
        title:menu.I18N['delete']
        ,msg:menu.I18N['confirmDelete']
        ,buttons:Ext.Msg.YESNO
        ,fn:this.deleteRow
        ,scope:this
        ,icon:Ext.MessageBox.QUESTION
      });  
      break;
    }
  },
  onToolbarClick:function(btn){
    switch (btn.id) {
    case 'add':
      this.addRow('add');
      break;
    }
  },
  addRow:function(func) {
    var store = this.getStore();
    var row = new store.recordType();
    store.fields.each(function(field) {
      row.data[field.name] = field.defaultValue;
    });
    var rowIndex = store.data.items.length;
    row.data['id'] = rowIndex;

    store.add(row);
    this.startEditing(rowIndex, 0);

    this.json.splice(rowIndex,0,row.data);
  },
  deleteRow:function(btn) {
    if (btn == 'no') return;

    iceCapXml.doDelete(this);
  }
});
Ext.reg('iceCapXml.gridToolbarFieldsGrid', iceCapXml.gridToolbarFieldsGrid);

// -----------------------------------------------------------------------
// Properties Form
// -----------------------------------------------------------------------

iceCapXml.propertiesForm = Ext.extend(Ext.form.FormPanel, {
  initComponent:function() {
    iceCapXml.resetPropertiesForm(this);
    Ext.apply(this, {
      id:'form_' + iceCapXml.count++
      ,renderTo:'form_body'
      ,labelAlign: 'left'
      ,buttonAlign: 'left'
      ,labelWidth:(this.labelWidth) ? this.labelWidth : 120
      ,border:false
      ,bodyStyle:'padding:5px 5px 0;'
      ,defaults:{
        width:50
      }
      ,autoWidth:true
      ,layout:'form'
      ,items:this.items
      ,buttons:[
        {
          text:'OK'
          ,handler:function() {
            if (this.form.isValid()) {
              this.save();
            }
          }
          ,scope:this
        },{
          text:menu.I18N['cancel']
          ,handler:function() {
            this.cancel();
          }
          ,scope:this
        }
      ]
    });
    iceCapXml.propertiesForm.superclass.initComponent.call(this);
  },
  afterRender:function() {
    var title = 'New (' + this.property + ')';
    // set form values from json
    if (this.func != 'add') {
      row = this.grid.getSelectionModel().getSelected();
      // find row in json object
      jsonIndex = iceCapXml.findJsonIndex(this.grid.json, row.data.id);
      this.form.setValues(this.grid.json[jsonIndex]);
      title = this.grid.json[jsonIndex].type;
    }
    // set title
    var centerPanel = this.grid.parent.center;
    centerPanel.panel.setTitle(menu.I18N['properties'] + ': "' + title + '"' );
    // set focus
    var field = this.form.items.items[0].name;
    this.form.findField(field).focus(true,10);

    iceCapXml.propertiesForm.superclass.afterRender.call(this);
  },
  save:function() {
    var me = this;
    
    // find grid row
    var row = {};
    var jsonIndex = -1;
    if (me.func == 'add') {
      // new element in json
      jsonIndex = me.grid.json.length;
      me.grid.json[jsonIndex] = {};
      me.grid.json[jsonIndex]['id'] = jsonIndex;

      // new element in grid store
      row = new me.grid.store.recordType();
      me.grid.store.fields.each(function(field) {
        row.data[field.name] = field.defaultValue;
      });
      row.data['id'] = jsonIndex;
      row.data['type'] = me.property;
      me.grid.json[jsonIndex]['type'] = me.property;
    } else {
      row = me.grid.getSelectionModel().getSelected();

      // find row in json object
      jsonIndex = iceCapXml.findJsonIndex(me.grid.json, row.data.id);
    }

    // save form fields
    me.form.items.each(function(field) {
      var value = field.getValue();
      switch (value) {
        case true:
          value = 'true';
          break;
        case false:
          value = 'false';
          break;
      }
      if (value != field.originalValue || me.func == 'add') {
        
        // update grid row
        var name = (field.name) ? field.name : field.hiddenName;

        row.set(name, value);
        
        // update json
        if (jsonIndex != -1) {
          if (name.indexOf('.') == -1) {
            me.grid.json[jsonIndex][name] = value;
          } else {
            var parent = name.substring(0, name.indexOf('.'));
            var child = name.substring(name.indexOf('.')+1);
            if (typeof (me.grid.json[jsonIndex][parent]) == 'undefined') me.grid.json[jsonIndex][parent] = {};
            me.grid.json[jsonIndex][parent][child] = value;
          }
        }

        iceCapXml.changePending = true;
      }
    });

    // save grid rows in form
    me.items.each(function(fs) {
      if (typeof (fs.items) != 'undefined') {
        fs.items.each(function(form) {
          if (typeof (form.items) != 'undefined') {
            form.items.each(function(grid) {
              if (typeof (grid.store) != 'undefined') {
                for (var i = 0; i < grid.store.data.items.length; i++) {
                  if (typeof(grid.subType) == 'undefined') {
                    me.grid.json[jsonIndex][grid.type].item[i] = grid.store.data.items[i].data;
                  } else {
                    me.grid.json[jsonIndex][grid.type][grid.subType].item[i] = grid.store.data.items[i].data;
                  }
                }
              }
            });
          }
        });
      }
    });

    // save grid rows without form
    me.items.each(function(fs) {
      if (typeof (fs.items) != 'undefined') {
        fs.items.each(function(grid) {
          if (typeof (grid.store) != 'undefined') {
            for (var i = 0; i < grid.store.data.items.length; i++) {
              if (typeof(grid.subType) == 'undefined') {
                me.grid.json[jsonIndex][grid.type].item[i] = grid.store.data.items[i].data;
              } else {
                me.grid.json[jsonIndex][grid.type][grid.subType].item[i] = grid.store.data.items[i].data;
              }
            }
          }
        });
      }
    });

    if (me.func == 'add') {
      me.grid.store.add(row);
    }
    iceCapXml.resetPropertiesForm(me);
  },
  cancel:function() {
    iceCapXml.resetPropertiesForm(this);
  }
});
Ext.reg('iceCapXml.propertiesForm', iceCapXml.propertiesForm);

// -----------------------------------------------------------------------
// Reset properties form
// -----------------------------------------------------------------------

iceCapXml.resetPropertiesForm = function(ct) {
  document.getElementById('form_body').innerHTML = '';

  var centerPanel = (typeof (ct.parent) != 'undefined') ? ct.parent.center.panel : ct.grid.parent.center.panel;
  centerPanel.setTitle(menu.I18N['properties']);
}

// -----------------------------------------------------------------------
// delete row (in grid and json)
// -----------------------------------------------------------------------

iceCapXml.doDelete = function(grid) {
  var row = {};
  var sm = grid.getSelectionModel();
  if (typeof (sm.getRowsSelected) == 'function') {
    rows = grid.getSelectionModel().getRowsSelected();
    row = grid.store.getAt(rows[0]);
  } else {
    row = sm.getSelected();
  } 
  grid.store.remove(row);

  var jsonIndex = iceCapXml.findJsonIndex(grid.json, row.data.id);
  if (jsonIndex != -1) {
    grid.json.splice(jsonIndex,1);
  }
}

// -----------------------------------------------------------------------
// Grid drag 'n drop
// -----------------------------------------------------------------------

iceCapXml.gridDragAndDrop = function(ddSource, e, data) {
  var sourceRowIndex = data.rowIndex;
  var targetRowIndex = ddSource.getDragData(e).rowIndex;

  var store = data.grid.getStore();
  var record = store.getAt(sourceRowIndex);

  var coords = e.getXY();
  dropWin = new Ext.Window({
    title:menu.I18N['whereToDrop']
    ,html:menu.I18N['DropBeforeOrAfter']
    ,width: 300
    ,height: 100
    ,minWidth: 60
    ,minHeight: 50
    ,buttonAlign:'center'
    ,bodyStyle:'padding:5px;'
    ,x:coords[0]
    ,y:coords[1]
    ,buttons:[
      {
        text: menu.I18N['before']
        ,handler: function() {
          store.removeAt(sourceRowIndex);
          if (targetRowIndex < sourceRowIndex) {
            store.insert(targetRowIndex,record);
            iceCapXml.moveArrayElement(data.grid.json, sourceRowIndex, targetRowIndex);
          } else {
            store.insert(targetRowIndex-1,record);
            iceCapXml.moveArrayElement(data.grid.json, sourceRowIndex, targetRowIndex-1);
          }
          dropWin.hide();
        }
      },{
        text: menu.I18N['after']
        ,handler: function() {
          store.removeAt(sourceRowIndex);
          if (targetRowIndex < sourceRowIndex) {
            store.insert(targetRowIndex+1,record);
            iceCapXml.moveArrayElement(data.grid.json, sourceRowIndex, targetRowIndex+1);
          } else {
            store.insert(targetRowIndex,record);
            iceCapXml.moveArrayElement(data.grid.json, sourceRowIndex, targetRowIndex);
          }
          dropWin.hide();
        }
      },{
        text: menu.I18N['cancel']
        ,handler: function() {
          dropWin.hide();
        }
      }
    ]
  });
  dropWin.show();
}

// -----------------------------------------------------------------------
// Extend Textfield
// -----------------------------------------------------------------------

iceCapXml.moveArrayElement = function(array, fromIndex, toIndex) {
  var tmp = array.splice(fromIndex, 1);
  array.splice(toIndex, 0, tmp[0]);
}

// -----------------------------------------------------------------------
// Extend Textfield
// -----------------------------------------------------------------------

iceCapXml.textField = Ext.extend(Ext.form.TextField, {
  initComponent:function() {
    Ext.apply(this, {
      width:(this.width) ? this.width : 50
    });
    iceCapXml.textField.superclass.initComponent.call(this);
  }
  ,afterRender:function() {
    this.on('focus', function(field) {
      var helpId = '';
      if (typeof (field.helpId) != 'undefined') {
        helpId = field.helpId;
      } else {
        helpId = iceCapXml.findHelpId(field);
      }
      if (helpId != null) {
        var f = (field.hiddenName) ? field.hiddenName : field.name;
        iceCapXml.getViewport().layout.east.panel.fireEvent('updateHelp', helpId + '_' + f);
      }
    });
    iceCapXml.textField.superclass.afterRender.call(this);
  }
});
Ext.reg('iceCapXml.textField', iceCapXml.textField);

// -----------------------------------------------------------------------
// Extend Numberfield
// -----------------------------------------------------------------------

iceCapXml.numberField = Ext.extend(Ext.form.NumberField, {
  initComponent:function() {
    Ext.apply(this, {
      width:(this.width) ? this.width : 50
    });
    iceCapXml.numberField.superclass.initComponent.call(this);
  }
  ,afterRender:function() {
    this.on('focus', function(field) {
      var helpId = iceCapXml.findHelpId(field);
      if (helpId != null) {
        var f = (field.hiddenName) ? field.hiddenName : field.name;
        iceCapXml.getViewport().layout.east.panel.fireEvent('updateHelp', helpId + '_' + f);
      }
    });
    iceCapXml.numberField.superclass.afterRender.call(this);
  }
});
Ext.reg('iceCapXml.numberField', iceCapXml.numberField);

// -----------------------------------------------------------------------
// Extend Checkbox
// -----------------------------------------------------------------------

iceCapXml.checkBox = Ext.extend(Ext.form.Checkbox, {
  initComponent:function() {
    Ext.apply(this, {
    });
    iceCapXml.checkBox.superclass.initComponent.call(this);
  }
  ,afterRender:function() {
    this.on('focus', function(field) {
      var helpId = iceCapXml.findHelpId(field);
      if (helpId != null) {
        var f = (field.hiddenName) ? field.hiddenName : field.name;
        iceCapXml.getViewport().layout.east.panel.fireEvent('updateHelp', helpId + '_' + f);
      }
    });
    iceCapXml.checkBox.superclass.afterRender.call(this);
  }
});
Ext.reg('iceCapXml.checkBox', iceCapXml.checkBox);

// -----------------------------------------------------------------------
// Extend Combobox
// -----------------------------------------------------------------------

iceCapXml.comboBox = Ext.extend(Ext.form.ComboBox, {
  initComponent:function() {
    Ext.apply(this, {
      width:(this.width) ? this.width : 50
      ,listWidth:(this.listWidth) ? this.listWidth : this.width
    });
    iceCapXml.comboBox.superclass.initComponent.call(this);
  }
  ,afterRender:function() {
    this.on('focus', function(field) {
      var helpId = iceCapXml.findHelpId(field);
      if (helpId != null) {
        var f = (field.hiddenName) ? field.hiddenName : field.name;
        iceCapXml.getViewport().layout.east.panel.fireEvent('updateHelp', helpId + '_' + f);
      }
    });
    iceCapXml.comboBox.superclass.afterRender.call(this);
  }
});
Ext.reg('iceCapXml.comboBox', iceCapXml.comboBox);

// -----------------------------------------------------------------------
// Region combo
// -----------------------------------------------------------------------

iceCapXml.regionCombo = Ext.extend(iceCapXml.comboBox, {
  initComponent:function() {
    iceCapXml.regions = [
      ['north']
      ,['east']
      ,['south']
      ,['west']
    ];
    Ext.apply(this, {
      fieldLabel:menu.I18N['contentLocation']
      ,hiddenName: 'contentLocation'
      ,store: new Ext.data.SimpleStore({
        fields: ['location']
        ,data : iceCapXml.regions 
      })
      ,displayField: 'location'
      ,typeAhead: true
      ,mode: 'local'
      ,triggerAction: 'all'
      ,selectOnFocus:true
      ,width:80
      ,listWidth:80
    });
    iceCapXml.regionCombo.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.regionCombo', iceCapXml.regionCombo);

// -----------------------------------------------------------------------
// Input type combo
// -----------------------------------------------------------------------

iceCapXml.inputTypeCombo = Ext.extend(iceCapXml.comboBox, {
  initComponent:function() {
    iceCapXml.regions = [
      ['inputWithInlineLabel', 'Input field with inline label']
      ,['input', 'Input field with normal label']
    ];
    Ext.apply(this, {
      fieldLabel:menu.I18N['type']
      ,hiddenName: 'type'
      ,store: new Ext.data.SimpleStore({
        fields: ['type', 'description']
        ,data : iceCapXml.regions 
      })
      ,displayField: 'description'
      ,valueField: 'type'
      ,typeAhead: true
      ,mode: 'local'
      ,triggerAction: 'all'
      ,selectOnFocus:true
      ,width:80
      ,listWidth:420
    });
    iceCapXml.inputTypeCombo.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.inputTypeCombo', iceCapXml.inputTypeCombo);

// -----------------------------------------------------------------------
// Datatype combo
// -----------------------------------------------------------------------

iceCapXml.dataTypeCombo = Ext.extend(iceCapXml.comboBox, {
  initComponent:function() {
    iceCapXml.dataTypes = [
      ['textfield']
      ,['numberfield']
    ];
    Ext.apply(this, {
      fieldLabel:menu.I18N['dataType']
      ,hiddenName: 'datatype'
      ,store: new Ext.data.SimpleStore({
        fields: ['datatype']
        ,data : iceCapXml.dataTypes 
      })
      ,displayField: 'datatype'
      ,typeAhead: true
      ,mode: 'local'
      ,triggerAction: 'all'
      ,selectOnFocus:true
      ,width:120
      ,listWidth:120
    });
    iceCapXml.dataTypeCombo.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.dataTypeCombo', iceCapXml.dataTypeCombo);


// -----------------------------------------------------------------------
// Datatype combo
// -----------------------------------------------------------------------

iceCapXml.breakoutFunctionCombo = Ext.extend(iceCapXml.comboBox, {
  initComponent:function() {
    var functions = [];
    var f = [];
    f[0] = menu.I18N['defaultAction'];
    f[1] = '';
    functions.push(f);

    for (o in IceCap.breakout) {
      var obj = IceCap.breakout[o];
      if (typeof (obj) == 'function') {
        var f = [];
        f[0] = (typeof (obj.description) != 'undefined') ? obj.description : o;
        f[1] = 'IceCap.breakout.' + o;
        functions.push(f);
      }
    }

    Ext.apply(this, {
      fieldLabel:menu.I18N['breakoutFunction']
      ,hiddenName: 'breakout'
      ,store: new Ext.data.SimpleStore({
        fields: ['description', 'breakout']
        ,data : functions 
      })
      ,displayField: 'description'
      ,valueField: 'breakout'
      ,typeAhead: true
      ,mode: 'local'
      ,triggerAction: 'all'
      ,selectOnFocus:true
      ,width:250
      ,listWidth:250
    });
    iceCapXml.breakoutFunctionCombo.superclass.initComponent.call(this);
  }
});
Ext.reg('iceCapXml.breakoutFunctionCombo', iceCapXml.breakoutFunctionCombo);

// -----------------------------------------------------------------------
// find panel for field on any level above
// -----------------------------------------------------------------------

iceCapXml.findHelpId = function(obj) {
  if (typeof (obj.ownerCt) == 'undefined') return null;

  if (typeof (obj.ownerCt.helpId) != 'undefined') {
    return obj.ownerCt.helpId;
  }
  
  var helpId = iceCapXml.findHelpId(obj.ownerCt);
  if (typeof (helpId) != 'undefined') return helpId;
}

// -----------------------------------------------------------------------
// find index in json object for matching id
// -----------------------------------------------------------------------

iceCapXml.findJsonIndex = function(json, id) {
  for (var i = 0; i < json.length; i++) {
    if (json[i].id == id) {
      return i;
      break;
    }
  }
  return -1;
}

// -----------------------------------------------------------------------
// find index in json object for matching id
// -----------------------------------------------------------------------

iceCapXml.getViewport = function() {
  var searchClass = 'viewport';
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	var els = document.getElementsByTagName('div');
	for(var i=0; i<els.length; i++) {
		if (pattern.test(els[i].className) ) {
      return Ext.getCmp(els[i].id);
    }
  }
  return null;
}

// -----------------------------------------------------------------------
// find index in json object for matching id
// -----------------------------------------------------------------------

iceCapXml.columns = function(items, labelWidth, columnWidth) {
  var columns = [];
  var children = [];

  for (var i = 0; i < items.length; i++) {
    if (typeof (children[items[i].columnNumber]) == 'undefined') {
      children[items[i].columnNumber] = {};
      children[items[i].columnNumber].items = [];
    }
    children[items[i].columnNumber].items.push(items[i]);
  }

  for (var i = 0; i < children.length; i++) {
    columns[i] = {};
    columns[i].layout         = 'form';
    columns[i].defaults       = {};
    columns[i].defaults.width = 50;

    if (typeof (labelWidth) != 'undefined' && typeof (labelWidth[i]) != 'undefined') {
      columns[i].labelWidth = labelWidth[i];
    }
    if (typeof (columnWidth) != 'undefined' && typeof (columnWidth[i]) != 'undefined') {
      columns[i].width = columnWidth[i];
    } else {
      columns[i].columnWidth = (100 / children.length) / 100;
    }
    columns[i].items          = children[i].items;
  }
  
  var output = 
    {
      layout:'column'
      ,width:462
      ,border:false
      ,defaults:{border:false}
      ,items:columns
    };
  return output;
}

// -----------------------------------------------------------------------
// Open window with IceCap API doc.
// -----------------------------------------------------------------------

iceCapXml.openWindow = function(url) {
  Ext.Ajax.request({
    url:url
    ,success: function ( result, request ) {
      var win = new Ext.Window({
        layout:'fit'
        ,width:800
        ,height:600
        ,autoScroll:true
        ,html:result.responseText
        ,title:'IceCap emulator API documentation'
        ,buttons:[
          {
            text:menu.I18N['closeWindow']
            ,handler:function() {
              win.close();
            }
          }
        ]
      })
      win.show();
    }
  });
}

// -----------------------------------------------------------------------
// set width for auto expand column
// -----------------------------------------------------------------------

iceCapXml.setAutoExpandColumnWidth = function(fs) {
  var grid = (typeof (fs.items.items[0].items) == 'undefined') ? fs.items.items[0] : fs.items.items[0].items.items[1];
  if (typeof(grid) != 'undefined') {
    var cm = grid.getColumnModel()
    var numberColumns = cm.getColumnCount();
    var width = 0;
    for (var i = 0; i < numberColumns-1; i++) {
      width += cm.getColumnWidth(i);
    } 
    width = (grid.width - width) - 20;
    cm.setColumnWidth(numberColumns-1, width);
  }
}

// -----------------------------------------------------------------------
// convert xml document to json object
// -----------------------------------------------------------------------

iceCapXml.xml2json = function(panel, xmlDoc) {
  var json = {};

  // panel
  var store = new Ext.data.Store({
    autoLoad:true
    ,proxy: new Ext.data.MemoryProxy(xmlDoc)
    ,reader: new Ext.data.XmlReader({
      record:''
    },[
        {name: 'id', mapping:'@id'}
        ,{name: 'token', mapping:'@token'}
      ]
    )
  });
  store.on('load', function(store, records, options) {
    json.id    = records[0].data.id;
    json.token = records[0].data.token;

    // select
    var store = new Ext.data.Store({
      autoLoad:true
      ,proxy: new Ext.data.MemoryProxy(xmlDoc)
      ,reader: new Ext.data.XmlReader({
        record:'select/when'
      },[
          {name: 'line', mapping:'@line'}
          ,{name: 'column', mapping:'@column'}
          ,{name: 'length', mapping:'@length'}
          ,{name: 'equal', mapping:'@equal'}
        ]
      )
    });
    store.on('load', function(store, records, options) {
      json.select = {};
      json.select['when'] = [];
      for (var i = 0; i < store.getCount(); i++) {
        var data = {};
        var rowData = store.getAt(i);
        rowData.data.id = i;
        rowData.data.type = menu.I18N['panelRecognition'];
        json.select['when'].push(rowData.data);
      };

      // areas
      var store = new Ext.data.Store({
        autoLoad:true
        ,proxy: new Ext.data.MemoryProxy(xmlDoc)
        ,reader: new Ext.data.XmlReader({
          record:'areas/property'
        },[
            // generel
            {name: 'type', mapping:'@type'}
            ,{name: 'startLine', mapping:'@startLine', type:'int', defaultValue:-1}
            ,{name: 'startColumn', mapping:'@startColumn', type:'int'}
            ,{name: 'endLine', mapping:'@endLine', type:'int', defaultValue:-1}
            ,{name: 'endColumn', mapping:'@endColumn', type:'int'}
            ,{name: 'xPosition', mapping:'@xPosition', type:'int'}
            ,{name: 'yPosition', mapping:'@yPosition', type:'int'}
            // input, output and label
            ,{name: 'line', mapping:'@line', type:'int'}
            ,{name: 'contentLocation', mapping:'@contentLocation'}
            // input, output
            ,{name: 'datatype', mapping:'@datatype'}
            ,{name: 'name', mapping:'@name'}
            ,{name: 'label', mapping:'@label'}
            ,{name: 'labelWidth', mapping:'@labelWidth', type:'int'}
            ,{name: 'labelSeparator', mapping:'@labelSeparator'}
            // input
            ,{name: 'maxLength', mapping:'@maxLength'}
            // area2grid
            ,{name: 'menuStartLine', mapping:'menu@startLine', type:'int', defaultValue:99}
            ,{name: 'menuEndLine', mapping:'menu@endLine', type:'int'}
            ,{name: 'moreOptionKey', mapping:'menu@moreOptionKey'}

            ,{name: 'columnStartLine', mapping:'column@startLine', type:'int', defaultValue:99}
            ,{name: 'columnEndLine', mapping:'column@endLine', type:'int'}
            ,{name: 'showOptionField', mapping:'column@showOptionField'}
            ,{name: 'optionFieldColumn', mapping:'column@optionFieldColumn'}
            ,{name: 'optionFieldLength', mapping:'column@optionFieldLength'}

            ,{name: 'quickOptionLine', mapping:'quickOption@line', type:'int'}

            ,{name: 'dataStartLine', mapping:'data@startLine', type:'int', defaultValue:99}
            ,{name: 'dataEndLine', mapping:'data@endLine', type:'int'}
            ,{name: 'subfileEndLine', mapping:'data@subfileEndLine', type:'int'}
            ,{name: 'subfileEndColumn', mapping:'data@subfileEndColumn', type:'int'}
            ,{name: 'subfileMoreText', mapping:'data@subfileMoreText'}
            ,{name: 'subfileBottomText', mapping:'data@subfileBottomText'}
            // area2columns
            ,{name: 'columnWidth', mapping:'@columnWidth'}
            ,{name: 'removeLabelDots', mapping:'@removeLabelDots'}
            // area2panel
            // area2commandLine
            ,{name: 'commandLine', mapping:'@commandLine'}
            ,{name: 'titleLine', mapping:'@titleLine'}
            ,{name: 'titleColumn', mapping:'@titleColumn'}
            ,{name: 'titleLength', mapping:'@titleLength'}
            ,{name: 'collapsible', mapping:'@collapsible'}
          ]
        )
      });
      store.on('load', function(store, records, options) {
        json.areas = {};
        json.areas['property'] = [];
        for (var i = 0; i < store.getCount(); i++) {
          var rowData = store.getAt(i);
          var data = {};
          data.type = rowData.data.type;
          data.attributes = {};
          if (data.type == 'area2grid') {
            data.attributes.startLine = Math.min(rowData.data.menuStartLine, rowData.data.columnStartLine, rowData.data.dataStartLine);
            data.attributes.endLine   = Math.max(rowData.data.menuEndLine, rowData.data.columnEndLine, rowData.data.dataEndLine);
          } else {
            if (rowData.data.startLine == -1) {
              data.attributes.startLine = rowData.data.line;
            } else {
              data.attributes.startLine = rowData.data.startLine;
            }
            if (rowData.data.endLine == -1) {
              data.attributes.endLine   = rowData.data.line;
            } else {
              data.attributes.endLine   = rowData.data.endLine;
            }
          }
          data.attributes.xPosition = rowData.data.xPosition;
          data.attributes.yPosition = rowData.data.yPosition;
    
          switch (data.type) {
          case 'input' :
            iceCapXml.inputXml2Json(data, rowData.data);
            break;
          case 'output' :
            iceCapXml.outputXml2Json(data, rowData.data);
            break;
          case 'label' :
            iceCapXml.labelXml2Json(data, rowData.data);
            break;
          case 'area2grid' :
            iceCapXml.area2gridXml2Json(data, rowData.data, xmlDoc);
            break;
          case 'area2columns' :
            iceCapXml.area2columnsXml2Json(data, rowData.data);
            break;
          case 'area2panel' :
            iceCapXml.area2panelXml2Json(data, rowData.data);
            break;
          case 'area2commandLine' :
            iceCapXml.area2commandLineXml2Json(data, rowData.data);
            break;
          case 'ignoreArea' :
            iceCapXml.ignoreAreaXml2Json(data, rowData.data);
            break;
          }
          data.id = i;
          json.areas['property'].push(data);
        };

        // key properties
        var store = new Ext.data.Store({
          autoLoad:true
          ,proxy: new Ext.data.MemoryProxy(xmlDoc)
          ,reader: new Ext.data.XmlReader({
            record:'keys'
          },[
              {name: 'startLine', mapping:'@startLine'}
              ,{name: 'endLine', mapping:'@endLine'}
            ]
          )
        });
        store.on('load', function(store, records, options) {
          json.keys = {};
          json.keys.startLine = records[0].data.startLine;
          json.keys.endLine   = records[0].data.endLine;

          // key items
          var store = new Ext.data.Store({
            autoLoad:true
            ,proxy: new Ext.data.MemoryProxy(xmlDoc)
            ,reader: new Ext.data.XmlReader({
              record:'keys/item'
            },[
                {name: 'key', mapping:'@id'}
                ,{name: 'text', mapping:'@text'}
              ]
            )
          });
          store.on('load', function(store, records, options) {
            json.keys['item'] = [];
            for (var i = 0; i < store.getCount(); i++) {
              var data = {};
              var rowData = store.getAt(i);
              rowData.data.id = i;
              rowData.data.type = menu.I18N['functionkey'];
              json.keys['item'].push(rowData.data);
            };
            panel.fireEvent('jsonReady', json);
          });
        });
      });
    });
  });
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : input
// -----------------------------------------------------------------------

iceCapXml.inputXml2Json = function(json, data) {
  json.line            = data.line;
  json.contentLocation = data.contentLocation;
  json.datatype        = data.datatype;
  json.name            = data.name;
  json.label           = data.label;
  json.labelWidth      = data.labelWidth;
  json.labelSeparator  = data.labelSeparator;
  json.maxLength       = data.maxLength;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : output
// -----------------------------------------------------------------------

iceCapXml.outputXml2Json = function(json, data) {
  json.line            = data.line;
  json.contentLocation = data.contentLocation;
  json.datatype        = data.datatype;
  json.name            = data.name;
  json.label           = data.label;
  json.labelWidth      = data.labelWidth;
  json.labelSeparator  = data.labelSeparator;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : label
// -----------------------------------------------------------------------

iceCapXml.labelXml2Json = function(json, data) {
  json.line            = data.line;
  json.contentLocation = data.contentLocation;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : area2grid
// -----------------------------------------------------------------------

iceCapXml.area2gridXml2Json = function(json, data, xmlDoc) {
  json.xPosition = data.xPosition;
  json.yPosition = data.yPosition;

  // grid menu
  json.menu = {};
  json.menu.startLine     = data.menuStartLine;
  json.menu.endLine       = data.menuEndLine;
  json.menu.moreOptionKey = data.moreOptionKey;
  var menus = new Ext.data.Store({
    autoLoad:true
    ,proxy: new Ext.data.MemoryProxy(xmlDoc)
    ,reader: new Ext.data.XmlReader({
      record:'areas/property/menu/item'
    },[
        {name: 'option', mapping:'@id'}
        ,{name: 'text', mapping:'@text'}
        ,{name: 'breakout', mapping:'@breakout'}
        ,{name: 'icon', mapping:'@icon'}
      ]
    )
  });
  menus.on('load', function(store) {
    json.menu['item'] = [];
    for (var i = 0; i < store.getCount(); i++) {
      var rowData = store.getAt(i);
      rowData.data.id = i;
      json.menu['item'].push(rowData.data);
    };
  });

  // grid column
  json.column = {};
  json.column.startLine         = data.columnStartLine;
  json.column.endLine           = data.columnEndLine;
  json.column.showOptionField   = data.showOptionField;
  json.column.optionFieldColumn = data.optionFieldColumn;
  json.column.optionFieldLength = data.optionFieldLength;
  var columns = new Ext.data.Store({
    autoLoad:true
    ,proxy: new Ext.data.MemoryProxy(xmlDoc)
    ,reader: new Ext.data.XmlReader({
      record:'areas/property/column/item'
    },[
        {name: 'header', mapping:'@header'}
        ,{name: 'columnStart', mapping:'@columnStart'}
      ]
    )
  });
  columns.on('load', function(store) {
    json.column['item'] = [];
    for (var i = 0; i < store.getCount(); i++) {
      var rowData = store.getAt(i);
      rowData.data.id = i;
      json.column['item'].push(rowData.data);
    };
  });

  // quick option
  json.quickOption = {};
  json.quickOption.line = data.quickOptionLine;

  // data
  json.data = {};
  json.data.startLine         = data.dataStartLine;
  json.data.endLine           = data.dataEndLine;
  json.data.subfileEndLine    = data.subfileEndLine;
  json.data.subfileEndColumn  = data.subfileEndColumn;
  json.data.subfileMoreText   = data.subfileMoreText;
  json.data.subfileBottomText = data.subfileBottomText;

  // toolbar
  json.toolbar         = {};
  json.toolbar.buttons = {};
  var toolbar = new Ext.data.Store({
    autoLoad:true
    ,proxy: new Ext.data.MemoryProxy(xmlDoc)
    ,reader: new Ext.data.XmlReader({
      record:'areas/property/toolbar/item'
    },[
        {name: 'button', mapping:'@id'}
        ,{name: 'text', mapping:'@text'}
      ]
    )
  });
  toolbar.on('load', function(store) {
    var count = store.getCount();
    if (count > 0) {
      json.toolbar.buttons['item'] = [];
      for (var i = 0; i < count; i++) {
        var rowData = store.getAt(i);
        rowData.data.id = i;
        json.toolbar.buttons['item'].push(rowData.data);
      };
    } else {
      var buttons = new Ext.data.Store({
        autoLoad:true
        ,proxy: new Ext.data.MemoryProxy(xmlDoc)
        ,reader: new Ext.data.XmlReader({
          record:'areas/property/toolbar/buttons/item'
        },[
            {name: 'button', mapping:'@id'}
            ,{name: 'text', mapping:'@text'}
          ]
        )
      });
      buttons.on('load', function(store) {
        var count = store.getCount();
        json.toolbar.buttons['item'] = [];
        for (var i = 0; i < count; i++) {
          var rowData = store.getAt(i);
          rowData.data.id = i;
          json.toolbar.buttons['item'].push(rowData.data);
        };
      });

      var fields = new Ext.data.Store({
        autoLoad:true
        ,proxy: new Ext.data.MemoryProxy(xmlDoc)
        ,reader: new Ext.data.XmlReader({
          record:'areas/property/toolbar/fields/item'
        },[
            {name: 'type', mapping:'@type'}
            ,{name: 'line', mapping:'@line'}
            ,{name: 'label', mapping:'@label'}
            ,{name: 'contentLocation', mapping:'@contentLocation'}
          ]
        )
      });
      fields.on('load', function(store) {
        var count = store.getCount();
        if (count > 0) {
          json.toolbar.fields = {};
          json.toolbar.fields['item'] = [];
          for (var i = 0; i < count; i++) {
            var rowData = store.getAt(i);
            rowData.data.id = i;
            json.toolbar.fields['item'].push(rowData.data);
          };
        };
      });
    }
  });
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : area2columns
// -----------------------------------------------------------------------

iceCapXml.area2columnsXml2Json = function(json, data) {
  json.xPosition       = data.xPosition;
  json.yPosition       = data.yPosition;
  json.startLine       = data.startLine;
  json.startColumn     = data.startColumn;
  json.endLine         = data.endLine;
  json.endColumn       = data.endColumn;
  json.columnWidth     = data.columnWidth;
  json.removeLabelDots = data.removeLabelDots;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : area2panel
// -----------------------------------------------------------------------

iceCapXml.area2panelXml2Json = function(json, data) {
  json.xPosition       = data.xPosition;
  json.yPosition       = data.yPosition;
  json.startLine       = data.startLine;
  json.startColumn     = data.startColumn;
  json.endLine         = data.endLine;
  json.endColumn       = data.endColumn;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : area2commandLine
// -----------------------------------------------------------------------

iceCapXml.area2commandLineXml2Json = function(json, data) {
  json.commandLine  = data.commandLine;
  json.titleLine    = data.titleLine;
  json.titleColumn  = data.titleColumn;
  json.titleLength  = data.titleLength;
  json.collapsible  = data.collapsible;
}

// -----------------------------------------------------------------------
// convert xml document to json object - Part : ignoreArea
// -----------------------------------------------------------------------

iceCapXml.ignoreAreaXml2Json = function(json, data) {
  json.startLine       = data.startLine;
  json.startColumn     = data.startColumn;
  json.endLine         = data.endLine;
  json.endColumn       = data.endColumn;
}

// -----------------------------------------------------------------------
// cell selection model with multi row selection
// -----------------------------------------------------------------------

iceCapXml.CellSelectionModelWithMultiRowSelect = function(config){
  Ext.apply(this, config);
  this.selections = [];
  this.last = false;
  this.lastActive = false;
  this.addEvents(
    "selectionchange",
    "beforecellselect",
    "cellselect",
    "celldeselect"
    );
  iceCapXml.CellSelectionModelWithMultiRowSelect.superclass.constructor.call(this);
};

Ext.extend(iceCapXml.CellSelectionModelWithMultiRowSelect, Ext.grid.AbstractSelectionModel,  {
  //if you want single cell selection or multiple
  singleSelect : false,

  //if on enter key to move to the next cell down
  moveEditorOnEnter: false,

  //if when a cell is selected with control or shift if the entire row should be selected
  rowSelection: true,

  // private
  initEvents : function(){
    if(!this.grid.enableDragDrop && !this.grid.enableDrag){
      this.grid.on("cellmousedown", this.handleMouseDown, this);
    }else{ // allow click to work like normal
      this.grid.on("cellclick", function(grid, rowIndex, columnIndex, e) {
        if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
          this.selectCell([rowIndex, columnIndex], false);
          grid.view.focusCell(rowIndex, columnIndex);
        }
      }, this);
    }
    this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
      "enter": function(e){
        var editor = this.grid.getColumnModel().getCellEditor(this.lastActive[1],this.lastActive[0]);
        if (editor){
          this.grid.startEditing(this.lastActive[0],this.lastActive[1]);
          this.clearSelections();
        }
      },
      "up" : function(e) {
        if (this.last === false) {
          this.selectCell([0, 0]);
        } else if (this.lastActive[0] === 0) {
          return;
        } else {
          var row, col;
          row = this.lastActive[0] - 1;
          col = this.lastActive[1];
          if (!e.shiftKey) {
            this.selectCell([row, col]);
          } else {
            var last = this.last
            this.selectRange(this.last, [row, col]);
            this.last = last;
          }
          this.grid.getView().focusCell(row, col);
          this.lastActive = [row, col];
        }
      },
      "down" : function(e) {
        if (this.last === false) {
          this.selectCell([0, 0]);
        } else if (this.lastActive[0] === this.grid.getStore().getCount() - 1) {
          this.addBottomRow(this);
          return;
        } else {
          var row, col;
          row = this.lastActive[0] + 1;
          col = this.lastActive[1];
          if (!e.shiftKey) {
            this.selectCell([row, col]);
          } else {
            var last = this.last
            this.selectRange(this.last, [row, col]);
            this.last = last;
          }
          this.grid.getView().focusCell(row, col);
          this.lastActive = [row, col];
        }
      },
      "left" : function(e) {
        if (this.last === false) {
          this.selectCell([0, 0]);
        } else if (this.lastActive[1] === 0) {
          return;
        } else {
          var row, col;
          row = this.lastActive[0];
          col = this.lastActive[1] - 1;
          if (!e.shiftKey) {
            this.selectCell([row, col]);
          } else {
            var last = this.last
            this.selectRange(this.last, [row, col]);
            this.last = last;
          }
          this.grid.getView().focusCell(row, col);
          this.lastActive = [row, col];
        }
      },
      "right" : function(e) {
        if (this.last === false) {
          this.selectCell([0, 0]);
        } else if (this.lastActive[1] === this.grid.getColumnModel().getColumnCount() - 1) { //NL
          if (this.lastActive[0] === this.grid.getStore().getCount() - 1) {
            this.addBottomRow(this);
          }
          return;
        } else {
          var row, col;
          row = this.lastActive[0];
          col = this.lastActive[1] + 1;
          if (!e.shiftKey) {
            this.selectCell([row, col]);
          } else {
            var last = this.last
            this.selectRange(this.last, [row, col]);
            this.last = last;
          }
          this.grid.getView().focusCell(row, col);
          this.lastActive = [row, col];
        }
      },
      scope: this
    });
    var view = this.grid.view;
    view.on("refresh", this.onRefresh, this);
    view.on("rowremoved", this.onRemove, this);
  },

  // private
  onRefresh : function(){
    this.clearSelections();
  },

  // private
  onRemove : function(v, index, r){
    this.deselectRange([index, 0], [index, this.grid.getColumnModel().getColumnCount()]);
  },

  //return total number of cells selected
  getCount : function(){
    return this.selections.length;
  },

  //pass
  //  keepExisting
  //return
  //  true if success
  selectRight : function(keepExisting){
    if(this.hasNext()){
      var row, col = this.last[1];
      if (col === this.grid.getColumnModel().getColumnCount() - 1) {
        row = this.last[0] + 1;
        col = 0;
      } else {
        row = this.last[0];
        col += 1;
      }

      this.selectCell([row, col], keepExisting);
      this.grid.getView().focusCell(this.last[0], this.last[1]);
      return true;
    }
    return false;
  },

  //pass
  //  keepExisting
  //return
  //  true if success
  selectDown : function(keepExisting) {
    var r, cols = this.grid.getColumnModel().getColumnCount();
    for (var i = 0; i < cols; i++) {
      r = this.selectRight(keepExisting);
      if (!r) break;
    }
    return r;
  },

  //pass
  //  keepExisting
  //return
  //  true if success
  selectUp : function(keepExisting) {
    var r, cols = this.grid.getColumnModel().getColumnCount();
    for (var i = 0; i < cols; i++) {
      r = this.selectLeft(keepExisting);
      if (!r) break;
    }
    return r;
  },

  //pass
  //  keepExisting
  //return
  //  true if success
  selectLeft : function(keepExisting) {
    if (this.hasPrevious()) {
      var row, col = this.last[1];
      if (col === 0) {
        row = this.last[0] - 1;
        col = this.grid.getColumnModel().getColumnCount() - 1;
      } else {
        row = this.last[0];
        col -= 1;
      }

      this.selectCell([row, col], keepExisting);
      this.grid.getView().focusCell(this.last[0], this.last[1]);
      return true;
    }
    return false;
  },

  //return
  //  true if next cell exists
  hasNext : function() {
    return this.last !== false && ((this.last[0] + 1) < this.grid.store.getCount() || (this.last[1] + 1) < this.grid.getColumnModel().getColumnCount());
  },

  //return
  //  true if previous cell exists
  hasPrevious : function(){
    return this.last !== false && (this.last[0] != 0 || this.last[1] != 0);
  },


  //return
  //  array of cells selected
  getSelections : function() {
    return [].concat(this.selections);
  },

  //return
  //  array of select rows
  getRowsSelected : function() {
    var s = this.selections;
    var results = [];
    for (var i=0; i<s.length; i++){
      var found = false;
      for (var j=0; j<results.length; j++){
        if (s[i][0] === results[j]){
          found = true;
        }
      }
      if (!found){
        results.push(s[i][0]);
      }
    }
    return results.reverse();
  },

  //return
  //  array of selected cols
  getColsSelected : function() {
    var s = this.selections;
    var results = [];
    for (var i=0; i<s.length; i++){
      var found = false;
      for (var j=0; j<results.length; j++){
        if (s[i][1] === results[j]){
          found = true;
        }
      }
      if (!found){
        results.push(s[i][1]);
      }
    }
    return results;
  },


  //return
  //  single selected row
  getSelectedCell : function() {
    return this.selections.length > 0 ? [].concat(this.selections[0]) : null;
  },

  //return
  //  last activated cell
  getLastActiveCell: function(){
    return this.lastActive;
  },

  //pass
  //  fn
  //  scope
  //return
  //  true if successfull
  each : function(fn, scope) {
    var s = this.getSelections();
    for (var i = 0, len = s.length; i < len; i++) {
      if (fn.call(scope || this, s[i], i) === false) {
        return false;
      }
    }
    return true;
  },

  //clears all selected cells
  clearSelections : function(){
    if(this.locked) return;
    for (var i = this.selections.length - 1; i >= 0 ; i--) {
      this.deselectCell(this.selections[i]);
    }
    this.selections = [];
    this.last = false;
  },


  //select all cells in grid
  selectAll : function(){
    if(this.locked) return;
    this.selections = [];
    var rowCount = this.grid.getStore().getCount();
    var colCount = this.grid.getColumnModel().getColumnCount();
    for(var row = 0; row < rowCount; row++){
      for(var col = 0; col < colCount; col++){
        this.selectCell([row, col], true);
      }
    }
  },

  //return
  //  true
  hasSelection : function(){
    return this.selections.length > 0;
  },

  //pass
  //  index - array of [row,col]
  isSelected : function(index){
    var s = this.selections;
    for (var i = 0; i < s.length; i++) {
      if (s[i][0] === index[0] && s[i][1] === index[1]) {
        return true;
      }
    }
    return false;
  },

  // private
  handleKeyDown : function(e) {
    var g = this.grid, s = this.selection;

    // If the cell is not selected and it's selectable then select it.
    // When does this happen?
    if (!s) {
      e.stopEvent();
      var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);
      if (cell) {
          this.select(cell[0], cell[1]);
      }
      return;
    }
    var sm = this;
    var walk = function(row, col, step){
      return g.walkCells(row, col, step, sm.isSelectable,  sm);
    };
    var k = e.getKey(), r = s.cell[0], c = s.cell[1];
    var newCell;

    if (!e.isNavKeyPress() && !e.isSpecialKey()) {
      var keyCode = k;
      /*
          The String.fromCharCode method is return the charactor in upper case so I'm converting
          it back to lower case then later checking if the shiftKey was used and converting to upper case.
      */
      var keyValue = String.fromCharCode(keyCode).toLowerCase();
      var record = g.getStore().getAt(r);
      var field = g.colModel.getDataIndex(c);

      // Shift + charector should be upper case charector.
      if (e.shiftKey) {
          keyValue = keyValue.toUpperCase();
      }

      g.startEditing(r, c);
      record.data[field] = keyValue;
    } else {
      switch(k){
        case e.TAB:
          if(e.shiftKey){
              newCell = walk(r, c-1, -1);
          }else{
              newCell = walk(r, c+1, 1);
          }
        break;
        case e.DOWN:
          newCell = walk(r+1, c, 1);

        break;
        case e.UP:
          newCell = walk(r-1, c, -1);
        break;
        case e.RIGHT:
          newCell = walk(r, c+1, 1);
        break;
        case e.LEFT:
          newCell = walk(r, c-1, -1);
        break;
        case e.ENTER:
          if(g.isEditor && !g.editing){
            g.startEditing(r, c);
            e.stopEvent();
            g.getView().focusCell(r, c);
            return;
          }
        break;
      }
    }
    if (newCell) {
      this.select(newCell[0], newCell[1]);
      e.stopEvent();
    }
  },

  // private
  handleMouseDown : function(g, rowIndex, columnIndex, e){
    if(typeof(e) == 'undefined' || e.button !== 0 || this.isLocked()){
      return;
    }
    var last = this.last;
    var view = this.grid.getView();
    if (e.ctrlKey && this.last !== false && this.rowSelection){
      this.selectRow([rowIndex, columnIndex], e.ctrlKey);
      this.last = last; // reset the last
      view.focusCell(rowIndex, columnIndex);
    }else if(e.shiftKey && this.last !== false){
      this.selectRange(last, [rowIndex, columnIndex], e.ctrlKey);
      this.last = last; // reset the last
      view.focusCell(rowIndex, columnIndex);
    }else{
      var isSelected = this.isSelected([rowIndex, columnIndex]);
      if(e.ctrlKey && isSelected){
        this.deselectCell([rowIndex, columnIndex]);
      }else if(!isSelected || this.getCount() > 1){
        this.selectCell([rowIndex, columnIndex], e.ctrlKey || e.shiftKey);
        view.focusCell(rowIndex, columnIndex);
      }
    }
  },

  //pass
  //  cell - [row,col]
  selectRow: function(cell){
    var row = cell[0];
    var selectCnt = 0;
    var colCnt = this.grid.getColumnModel().getColumnCount();
    for (var col = 0; col <= colCnt; col++) {
      if (this.isSelected([row, col])){
        selectCnt++;
      }
    }
    if (selectCnt > 1){
      this.deselectRange([row,0], [row,colCnt], false);
    }else{
      this.selectRange([row, 0], [row,colCnt], true);
    }
  },

  //pass
  //  cells - array ([row,col])
  //  keepExisting
  selectCells : function(cells, keepExisting){
    if(!keepExisting){
      this.clearSelections();
    }
    for(var i = 0, len = cells.length; i < len; i++){
      this.selectCell(cells[i], true);
    }
  },

  //pass
  //  startCell
  //  endCell
  //  keepExisting
  selectRange : function(startCell, endCell, keepExisting){
    if(this.locked) return;
    if(!keepExisting){
      this.clearSelections();
    }
    var row;
    var col;
    var startRow = startCell[0];
    var startCol = startCell[1];
    var endRow = endCell[0];
    var endCol = endCell[1];
    if (endRow < startRow) {
      row = endRow;
      endRow = startRow;
      startRow = row;
    }
    if (endCol < startCol) {
      col = endCol;
      endCol = startCol;
      startCol = col;
    }
    if (this.rowSelection){
      for (row = startRow; row <= endRow; row++) {
        for (col = 0; col <= this.grid.getColumnModel().getColumnCount(); col++) {
          this.selectCell([row, col], true);
        }
      }
    }else{
      for (row = startRow; row <= endRow; row++) {
        for (col = startCol; col <= endCol; col++) {
          this.selectCell([row, col], true);
        }
      }
    }
  },

  //pass
  //  startCell
  //  endCell
  //  preventViewNotify
  deselectRange : function(startCell, endCell, preventViewNotify) {
    if(this.locked) return;
    var row;
    var col;
    var startRow = startCell[0];
    var startCol = startCell[1];
    var endRow = endCell[0];
    var endCol = endCell[1];
    if (endRow < startRow) {
      // flip 'em
      row = endRow;
      endRow = startRow;
      startRow = row;
    }
    if (endCol < startCol) {
      // flip 'em
      col = endCol;
      endCol = startCol;
      startCol = col;
    }
    if (this.rowSelection){
      for (row = startRow; row <= endRow; row++) {
        for (col = 0; col <= this.grid.getColumnModel().getColumnCount(); col++) {
          this.deselectCell([row, col], preventViewNotify);
        }
      }
    }else{}
    for (row = startRow; row <= endRow; row++) {
      for (col = startCol; col <= endCol; col++) {

        this.deselectCell([row, col], preventViewNotify);
      }
    }
  },

  //pass
  //  cell
  //  keepExisting
  //  preventViewNotify
  selectCell : function(cell, keepExisting, preventViewNotify){
    if (this.locked) return;
    if (this.isSelected(cell)) return;
    var row = cell[0];
    var col = cell[1];
    if (row < 0 || row >= this.grid.store.getCount()) return;
    if (col < 0 || col >= this.grid.getColumnModel().getColumnCount()) return;

    if (this.fireEvent("beforecellselect", this, cell, keepExisting) !== false) {
      if (!keepExisting || this.singleSelect) {
        this.clearSelections();
      }
      this.selections.push(cell);
      this.last = this.lastActive = cell;
      if(!preventViewNotify) {
        this.grid.getView().onCellSelect(row, col);
      }
      this.fireEvent("cellselect", this, cell);
      this.fireEvent("selectionchange", this, [].concat(this.selections));
    }
  },

  //pass
  //  cell
  //  preventViewNotify
  deselectCell : function(cell, preventViewNotify){
    if (this.locked) return;
    if (this.last[0] === cell[0] && this.last[1] === cell[1]) {
      this.last = false;
    }
    if (this.lastActive[0] === cell[0] && this.lastActive[1] === cell[1]) {
      this.lastActive = false;
    }

    var s = this.selections;
    for (var i = 0; i < s.length; i++) {
      if (s[i][0] === cell[0] && s[i][1] === cell[1]) {
        this.selections.remove(s[i]);
        if (!preventViewNotify) {
          this.grid.getView().onCellDeselect(cell[0], cell[1]);
        }
        this.fireEvent("celldeselect", this, cell);
        this.fireEvent("selectionchange", [].concat(this.selections));
        return;
      }
    }

  },

  // private
  acceptsNav : function(row, col, cm){
    return !cm.isHidden(col) && cm.isCellEditable(col, row);
  },
  // private
  onEditorKey : function(field, e){
    var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
    if (k == e.TAB) {
      if(e.shiftKey){
        newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
      } else {
        newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
        if (this.grid.getStore().getCount() -1  == ed.row
        &&  this.grid.getColumnModel().getColumnCount() - 1 == ed.col) {
          this.addBottomRow(this);
        } else {
        }
      }
      e.stopEvent();
    } else if (k == e.ENTER) {
      ed.completeEdit();
      e.stopEvent();
    } else if (k == e.ESC) {
      e.stopEvent();
      ed.cancelEdit();
      this.selectCell([ed.row, ed.col]);
    } else if (k == e.DOWN && !ed.field.disableArrowsUpDown) {
      ed.completeEdit();
      e.stopEvent();
      newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
      ed.field.focus(true);
    } else if (k == e.UP && !ed.field.disableArrowsUpDown) {
      ed.completeEdit();
      e.stopEvent();
      newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
      ed.field.focus(true);
    }
    if (newCell) {
      if (this.ihubAddingRow){
        this.ihubAddingRow = false;
        this.clearSelections();
      }else{
        this.clearSelections();
        this.selectCell(newCell);
        g.startEditing(newCell[0], newCell[1]);
      }
    }
  }
});