(function () {
    "use strict";

    var const_undefined = "undefined";

    //<editor-fold desc="Help Methods">
    function subclass(target, methodName, redirectFn) {
        var oldMethodRenamed = "_o_" + methodName;
        if (target.prototype.hasOwnProperty(oldMethodRenamed)) {
            throw new Error("override method conflit");
        }
        target.prototype[oldMethodRenamed] = target.prototype[methodName];
        target.prototype[methodName] = redirectFn;
    }

    function bindToBaseCall(target, obj, methodName) {
        var oldMethodRenamed = "_o_" + methodName;
        var fn = null;
        if (target && target.prototype.hasOwnProperty(oldMethodRenamed)) {
            fn = target.prototype[oldMethodRenamed];
        }
        if (!fn || typeof fn !== "function") {
            if (obj !== null && obj !== undefined && obj.hasOwnProperty(methodName)) {
                fn = obj[methodName];
            }
            if (!fn || typeof fn !== "function") {
                fn = function () {
                    // do nothing.
                };
            }
        }
        return function () {
            return fn.apply(obj, arguments);
        };
    }

    function overrideClassMethod(target, methodName, redirectFn) {
        var oldMethodRenamed = "_o_" + methodName;
        if (target.hasOwnProperty(oldMethodRenamed)) {
            throw new Error("override method conflit");
        }
        target[oldMethodRenamed] = target[methodName];
        target[methodName] = redirectFn;
    }

    function convertToStyle(jsStyle) {
        if (!jsStyle) {
            return null;
        }

        var style = new GrapeCity.UI.Style();
        if (jsStyle.IsBackColorSet) {
            style.backColor = jsStyle.BackColor;
        }
        if (jsStyle.IsBackgroundImageSet) {
            style.backgroundImage = jsStyle.BackgroundImage;
        }
        if (jsStyle.IsForeColorSet) {
            style.foreColor = jsStyle.ForeColor;
        }
        if (jsStyle.IsHAlignSet) {
            style.hAlign = jsStyle.HAlign;
        }
        if (jsStyle.IsVAlignSet) {
            style.vAlign = jsStyle.VAlign;
        }
        if (jsStyle.IsFontSet) {
            style.font = jsStyle.Font;
        }
        if (jsStyle.IsThemeFontSet) {
            style.themeFont = jsStyle.ThemeFont;
        }
        if (jsStyle.IsFormatterSet) {
            style.formatter = jsStyle.Formatter;
        }

        if (jsStyle.IsValidatorSet) {
            if (jsStyle.Validator) {
                var validator = jsStyle.Validator;
                var type = validator.CriteriaType,
                    op = validator.ComparisonOperator,
                    v1 = validator.Value1,
                    v2 = validator.Value2;
                var dv;
                switch (type) {
                    case GrapeCity.UI.CriteriaType.WholeNumber:
                        dv = GrapeCity.UI.DefaultDataValidator.createNumberValidator(op, v1, v2, true);
                        break;
                    case GrapeCity.UI.CriteriaType.DecimalValues:
                        dv = GrapeCity.UI.DefaultDataValidator.createNumberValidator(op, v1, v2, false);
                        break;
                    case GrapeCity.UI.CriteriaType.Date:
                        dv = GrapeCity.UI.DefaultDataValidator.createDateValidator(op, v1, v2);
                        break;
                    case GrapeCity.UI.CriteriaType.TextLength:
                        dv = GrapeCity.UI.DefaultDataValidator.createTextLengthValidator(op, v1, v2);
                        break;
                    case GrapeCity.UI.CriteriaType.Custom:
                        dv = GrapeCity.UI.DefaultDataValidator.createFormulaValidator(v1);
                        break;
                    case GrapeCity.UI.CriteriaType.List:
                        if (v1 && v1.charAt(0) === "=") {
                            dv = GrapeCity.UI.DefaultDataValidator.createFormulaListValidator(v1);
                        } else {
                            dv = GrapeCity.UI.DefaultDataValidator.createListValidator(v1);
                        }
                        break;
                }
                if (dv) {
                    dv.errorStyle = validator.ErrorStyle;
                    dv.ignoreBlank = validator.IgnoreBlank;
                    dv.inCellDropdown = validator.InCellDropdown;
                    dv.showInputMessage = validator.ShowInputMessage;
                    dv.showErrorMessage = validator.ShowErrorMessage;
                    dv.inputTitle = validator.InputTitle;
                    dv.errorTitle = validator.ErrorTitle;
                    dv.inputMessage = validator.InputMessage;
                    dv.errorMessage = validator.ErrorMessage;
                    if (dv.inputMessage) {
                        dv.inputMessage = dv.inputMessage.replace(/\r\n/g, "<br/>");
                    }
                    if (dv.errorMessage) {
                        dv.errorMessage = dv.errorMessage.replace(/\r\n/g, "<br/>");
                    }
                }
                style.validator = dv;
            } else {
                style.validator = null;
            }
        }

        if (jsStyle.IsBorderLeftSet) {
            if (jsStyle.BorderLeft) {
                var border = jsStyle.BorderLeft;
                style.borderLeft = new GrapeCity.UI.LineBorder(border.Color, border.Style);
            } else {
                style.borderLeft = null;
            }
        }
        if (jsStyle.IsBorderTopSet) {
            if (jsStyle.BorderTop) {
                border = jsStyle.BorderTop;
                style.borderTop = new GrapeCity.UI.LineBorder(border.Color, border.Style);
            } else {
                style.borderTop = null;
            }
        }
        if (jsStyle.IsBorderRightSet) {
            if (jsStyle.BorderRight) {
                border = jsStyle.BorderRight;
                style.borderRight = new GrapeCity.UI.LineBorder(border.Color, border.Style);
            } else {
                style.borderRight = null;
            }
        }
        if (jsStyle.IsBorderBottomSet) {
            if (jsStyle.BorderBottom) {
                border = jsStyle.BorderBottom;
                style.borderBottom = new GrapeCity.UI.LineBorder(border.Color, border.Style);
            } else {
                style.borderBottom = null;
            }
        }

        if (jsStyle.IsLockedSet) {
            style.locked = jsStyle.Locked;
        }
        if (jsStyle.IsTextIndentSet) {
            style.textIndent = jsStyle.TextIndent;
        }
        if (jsStyle.IsWordWrapSet) {
            style.wordWrap = jsStyle.WordWrap;
        }
        if (jsStyle.IsShrinkToFitSet) {
            style.shrinkToFit = jsStyle.ShrinkToFit;
        }
        return style;
    }

    function convertToRange(jsRange) {
        if (!jsRange) {
            return null;
        }

        var rg = new GrapeCity.UI.Range();
        rg.row = jsRange.Row;
        rg.rowCount = jsRange.RowCount;
        rg.col = jsRange.Column;
        rg.colCount = jsRange.ColumnCount;

        return rg;
    }

    function convertToRanges(jsRanges) {
        if (!jsRanges) {
            return null;
        }

        var rgs = new Array();
        for (var i = 0; i < jsRanges.length; i++) {
            rgs.push(convertToRange(jsRanges[i]));
        }
        return rgs;
    }

    function convertToSparklineSetting(jsSetting) {
        if (!jsSetting) {
            return null;
        }

        var st = new GrapeCity.UI.SparklineSetting();

        st.axisColor(jsSetting.AxisColor);
        st.firstMarkerColor(jsSetting.FirstMarkerColor);
        st.highMarkerColor(jsSetting.HighMarkerColor);
        st.lastMarkerColor(jsSetting.LastMarkerColor);
        st.lowMarkerColor(jsSetting.LowMarkerColor);
        st.markersColor(jsSetting.MarkersColor);
        st.negativeColor(jsSetting.NegativeColor);
        st.seriesColor(jsSetting.SeriesColor);

        st.showFirst(jsSetting.ShowFirst);
        st.showHigh(jsSetting.ShowHigh);
        st.showLast(jsSetting.ShowLast);
        st.showLow(jsSetting.ShowLow);
        st.showNegative(jsSetting.ShowNegative);
        st.showMarkers(jsSetting.ShowMarkers);

        st.displayEmptyCellsAs = jsSetting.DisplayEmptyCellsAs;
        st.rightToLeft = jsSetting.RightToLeft;

        st.displayHidden = jsSetting.DisplayHidden;
        st.displayXAxis = jsSetting.DisplayXAxis;

        st.manualMax = jsSetting.ManualMax;
        st.manualMin = jsSetting.ManualMin;
        st.maxAxisType = jsSetting.MaxAxisType;
        st.minAxisType = jsSetting.MinAxisType;

        st.groupMaxValue = jsSetting.GroupMaxValue;
        st.groupMinValue = jsSetting.GroupMinValue;
        st.lineWeight = jsSetting.LineWeight;

        return st;
    }

    function convertToSXValue(value) {
        if (value instanceof Date) {
            // convert date
            value = "/Date(" + value.getTime() + ")/";
        } else if(value instanceof Number) {
            value = value.valueOf();
        }

        return value;
    }

    function doGroupObjectFromJSON(spreadObject, sheetName, groupJSON, isRowGroup) {
        if (!spreadObject || !groupJSON) {
            return;
        }
        if (groupJSON.itemsData) {
            var length = groupJSON.itemsData.length;
            for (var i = 0; i < length; i++) {
                var item = groupJSON.itemsData[i];
                if (item.count > 0 && item.index >= 0 && item.info) {
                    for (var k = 0; k < item.count; k++) {
                        if (item.index + k >= groupJSON.itemsCount) {
                            break;
                        }
                        spreadObject.SetLevel(sheetName, isRowGroup, item.index + k, item.info.level);
                    }
                }
            }
            for (var i = 0; i < length; i++) {
                var item = groupJSON.itemsData[i];
                if (item.count > 0 && item.index >= 0 && item.info) {
                    spreadObject.SetCollapsed(sheetName, isRowGroup, item.index, !!item.info.collapsed);
                }
            }
        }
        if (groupJSON.direction !== null && groupJSON.direction !== undefined) {
            spreadObject.SetRangeGroupDirection(sheetName, isRowGroup, groupJSON.direction);
        }
    }

    function doSpreadObjectFromJSON(spreadObject, spreadJson) {
        if (!spreadObject || !spreadJson) {
            return;
        }

        var t = spreadObject, jsonData = spreadJson;
        t.Suspend();
        try {
            t.ClearSheets();
            t.SetSheetCount(jsonData.sheetCount);

            if (jsonData.referenceStyle !== null && jsonData.referenceStyle !== undefined) {
                t.SetSpreadReferenceStyle(jsonData.referenceStyle);
            }

            var i = 0;
            if(jsonData.sheets) {
                for(var s in jsonData.sheets) {
                    if(typeof(s) === "string") {
                        var sheetData = jsonData.sheets[s];
                        t.SetNameFromJson(i, sheetData.name);
                        doSheetObjectFromJSON(t, sheetData);
                        i++;
                    }
                }
            }

            t.SetActiveSheetIndex(jsonData.activeSheetIndex);

            if (typeof(jsonData.tabStripRatio) !== const_undefined) {
                t.SetTabStripRatio(jsonData.tabStripRatio);
            }
            if (typeof(jsonData.tabStripVisible) !== const_undefined) {
                t.SetTabStripVisible(jsonData.tabStripVisible);
            }
            if (typeof(jsonData.tabEditable) !== const_undefined) {
                t.SetTabEditable(jsonData.tabEditable);
            }
            if (typeof(jsonData.newTabVisible) !== const_undefined) {
                t.SetNewTabVisible(jsonData.newTabVisible);
            }
            if (typeof(jsonData.canUserEditFormula) !== const_undefined) {
                t.AllowUserFormula = jsonData.canUserEditFormula;
            }
            if (typeof(jsonData.startSheetIndex) !== const_undefined) {
                t.StartSheetIndex = jsonData.startSheetIndex;
            }

            if (typeof(jsonData.allowUndo) !== const_undefined) {
                t.SetAllowUndo(jsonData.allowUndo);
            }
            if (typeof(jsonData.allowUserZoom) !== const_undefined) {
                t.AllowUserZoom = jsonData.allowUserZoom;
            }
            if (typeof(jsonData.allowDragDrop) !== const_undefined) {
                t.SetCanUserDragDrop(jsonData.allowDragDrop);
            }
            if (typeof(jsonData.allowDragFill) !== const_undefined) {
                t.SetCanUserDragFill(jsonData.allowDragFill);
            }
            if (typeof(jsonData.highlightInvalidData) !== const_undefined) {
                t.HighlightInvalidData = jsonData.highlightInvalidData;
            }

            if (jsonData.names) {
                for (var n = 0; n < jsonData.names.length; n++) {
                    var ni = jsonData.names[n];
                    t.AddCustomName(ni.name, ni.formula, ni.row, ni.col);
                }
            }

            t.Invalidate();

        } finally {
            t.Resume()
        }
    }

    function doSheetObjectFromJSON(spreadObject, sheetJson) {
        if (!spreadObject || !sheetJson) {
            return;
        }
        if (spreadObject.IsUpdating) {
            return;
        }

        var SheetArea = GrapeCity.UI.SheetArea;
        var t = spreadObject, jsonData = sheetJson;
        var name = jsonData.name;
        var rowCount = jsonData.rowCount;
        var columnCount = jsonData.columnCount;

        t.SetRowCount(name, rowCount, GrapeCity.UI.SheetArea.viewport);
        t.SetColumnCount(name, columnCount, GrapeCity.UI.SheetArea.viewport);
        t.SetActiveCell(name, jsonData.activeRow, jsonData.activeCol);
        t.SetFrozenCount(name, jsonData.frozenRowCount, jsonData.frozenColCount);
        t.SetGridlineOptions(name, jsonData.gridline.color, jsonData.gridline.showVerticalGridline, jsonData.gridline.showHorizontalGridline);
        t.CanCellOverflow = jsonData.allowCellOverflow;

        if (typeof(jsonData.referenceStyle) !== const_undefined) {
            t.SetSheetReferenecStyle(name, jsonData.referenceStyle);
        }
        if (typeof(jsonData._zoomFactor) !== const_undefined) {
            t.Zoom(name, jsonData._zoomFactor);
        }

        if (jsonData.defaults) {
            if (typeof(jsonData.defaults.rowHeight) !== const_undefined) {
                t.SetDefaultRowHeight(name, jsonData.defaults.rowHeight);
            }
            if (typeof(jsonData.defaults.colWidth) !== const_undefined) {
                t.SetDefaultColumnWidth(name, jsonData.defaults.colWidth);
            }
            if (typeof(jsonData.defaults.rowHeaderColWidth) !== const_undefined) {
                t.SetDefaultRowHeaderColumnWidth(name, jsonData.defaults.rowHeaderColWidth);
            }
            if (typeof(jsonData.defaults.colHeaderRowHeight) !== const_undefined) {
                t.SetDefaultColumnHeaderRowHeight(name, jsonData.defaults.colHeaderRowHeight);
            }
        }

        //data source, not support now
        if(typeof(jsonData.autoGenerateColumns) !== const_undefined) {
            //in spreadjs autoGenerateColumns control both AutoGenerateColumns and DataAutoHeadings in SX.
            t.SetAutoGenerateColumns(name, jsonData.autoGenerateColumns);
            t.SetDataAutoHeadings(name, jsonData.autoGenerateColumns);
        }
        if (jsonData.dataSource) {
            //todo
        }

        //row axis
        if (jsonData.rows) {
            var rowInfos = jsonData.rows;
            for (var ri in rowInfos) {
                if (!isNaN(ri)) {
                    var r = parseInt(ri, 10);
                    t.SetRowInfo(name, r, rowInfos[ri], SheetArea.viewport);
                }
            }
        }
        //column axis
        if (jsonData.columns) {
            var colInfos = jsonData.columns;
            for (var ci in colInfos) {
                if (!isNaN(ci)) {
                    var c = parseInt(ci, 10);
                    t.SetColumnInfo(name, c, colInfos[ci], SheetArea.viewport);
                }
            }
        }
        //column styles
        if (jsonData.colStyles) {
            for (var ci in jsonData.colStyles) {
                if (!isNaN(ci)) {
                    var c = parseInt(ci, 10);
                    t.SetStyle(name, -1, c, jsonData.colStyles[ci], SheetArea.viewport);
                }
            }
        }
        //row styles
        if (jsonData.rowStyles) {
            for (var ri in jsonData.rowStyles) {
                if (!isNaN(ri)) {
                    var r = parseInt(ri, 10);
                    t.SetStyle(name, r, -1, jsonData.rowStyles[ri], SheetArea.viewport);
                }
            }
        }
        //header axis
        if (jsonData.rowHeaderColInfos) {
            var colInfos = jsonData.rowHeaderColInfos;
            for (var ci in colInfos) {
                if (!isNaN(ci)) {
                    var c = parseInt(ci, 10);
                    t.SetColumnInfo(name, c, colInfos[ci], SheetArea.rowHeader);
                }
            }
        }
        if (jsonData.colHeaderRowInfos) {
            var rowInfos = jsonData.colHeaderRowInfos;
            for (var ri in rowInfos) {
                if (!isNaN(ri)) {
                    var r = parseInt(ri, 10);
                    t.SetRowInfo(name, r, rowInfos[ri], SheetArea.colHeader);
                }
            }
        }

        //header autoText
        if (typeof(jsonData.rowHeaderAutoText) !== const_undefined) {
            t.SetRowHeaderAutoText(name, jsonData.rowHeaderAutoText);
        }
        if (typeof(jsonData.colHeaderAutoText) !== const_undefined) {
            t.SetColHeaderAutoText(name, jsonData.colHeaderAutoText);
        }

        //header autoTextIndex
        if (typeof(jsonData.rowHeaderAutoTextIndex) !== const_undefined) {
            t.SetRowHeaderAutoTextIndex(name, jsonData.rowHeaderAutoTextIndex);
        }
        if (typeof(jsonData.colHeaderAutoTextIndex) !== const_undefined) {
            t.SetColHeaderAutoTextIndex(name, jsonData.colHeaderAutoTextIndex);
        }

        //header visible
        if (typeof(jsonData.rowHeaderVisible) !== const_undefined) {
            t.SetRowHeaderVisible(name, jsonData.rowHeaderVisible);
        }
        if (typeof(jsonData.colHeaderVisible) !== const_undefined) {
            t.SetColumnHeaderVisible(name, jsonData.colHeaderVisible);
        }

        //header count
        if (typeof(jsonData.rowHeaderColCount) !== const_undefined) {
            t.SetColumnCount(name, jsonData.rowHeaderColCount, SheetArea.rowHeader);
        }
        if (typeof(jsonData.colHeaderRowCount) !== const_undefined) {
            t.SetRowCount(name, jsonData.colHeaderRowCount, SheetArea.colHeader);
        }

        //row header span
        if(jsonData.rowHeaderSpan) {
            doSpansFromJSON(t, name, jsonData.rowHeaderSpan, SheetArea.rowHeader);
        }

        //row header data
        if(jsonData.rowHeaderData) {
            doDataFromJSON(t, name, jsonData.rowHeaderData, SheetArea.rowHeader);
        }

        //col header span
        if(jsonData.colHeaderSpan) {
            doSpansFromJSON(t, name, jsonData.colHeaderSpan, SheetArea.colHeader);
        }

        //col header data
        if(jsonData.colHeaderData) {
            doDataFromJSON(t, name, jsonData.colHeaderData, SheetArea.colHeader);
        }

        //viewport span
        if (jsonData.spans) {
            doSpansFromJSON(t, name, jsonData.spans, SheetArea.viewport);
        }

        //selections
        if (jsonData.selections) {
            doSelectionsFromJSON(t, name, jsonData.selections);
        }

        //viewport data
        if (jsonData.data) {
            doDataFromJSON(t, name, jsonData.data, SheetArea.viewport);
        }

        //theme
        if (jsonData.theme) {
            var st = jsonData.theme;
            if (typeof st === "string" || typeof st === "undefined") {
                t.CurrentThemeName = st;
            } else {
                //st._name, st._headingFont, st._bodyFont, st._themeColor
                t.CurrentThemeName = st._name;
            }
        }

        //group
        if (typeof(jsonData.showRowRangeGroup) !== const_undefined) {
            t.ShowRowRangeGroup = jsonData.showRowRangeGroup;
        }
        if (typeof(jsonData.showColumnRangeGroup) !== const_undefined) {
            t.ShowColumnRangeGroup = jsonData.showColumnRangeGroup;
        }
        if (jsonData.rowRangeGroup) {
            doGroupObjectFromJSON(t, name, jsonData.rowRangeGroup, true);
        }
        if (jsonData.colRangeGroup) {
            doGroupObjectFromJSON(t, name, jsonData.colRangeGroup, false);
        }

        //filter
        if (jsonData.rowFilter) {
            var settings = jsonData.rowFilter;
            var range = settings.range;
            t.SetRowFilter(name, range);
            if (settings.filterItemMap) {
                for (var i = 0; i < settings.filterItemMap.length; i++) {
                    var conditionArray = settings.filterItemMap[i].conditions;
                    if (conditionArray) {
                        for (var k = 0; k < conditionArray.length; k++) {
                            var conditionSettings = conditionArray[k];
                            if (conditionSettings) {
                                t.AddFilterItem(name, settings.filterItemMap[i].index, conditionSettings);
                            }
                        }
                    }
                }
            }

            if (settings.filteredColMap) {
                for (var i = 0; i < settings.filteredColMap.length; i++) {
                    var filteredCol = settings.filteredColMap[i];
                    if (filteredCol !== undefined && filteredCol !== null) {
                        t.Filter(name, filteredCol);
                    }
                }
            }

            if (settings.sortInfo) {
                t.SortColumn(name, settings.sortInfo.index, settings.sortInfo.ascending);
            }

            if (settings.showFilterButton !== null && settings.showFilterButton !== undefined) {
                t.SetShowFilterButton(name, settings.showFilterButton);
            }
        }

        if (jsonData.sheetTabColor) {
            t.SetSheetTabColor(name, jsonData.sheetTabColor);
        }

        //conditional formats
        if(jsonData.conditionalFormats) {
            t.DoConditionalFormatsFromJSON(name, jsonData.conditionalFormats);
        }

        if (typeof(jsonData.isProtected) !== const_undefined) {
            t.SetSheetProtected(name, jsonData.isProtected);
        }

        t.InvalidateSheet(name);
    }

    function doSpansFromJSON(spreadObject, sheetName, spans, sheetArea) {
        if (!spans || !spreadObject || !sheetName) {
            return;
        }

        var t = spreadObject, name = sheetName;
        for (var j = 0; j < spans.length; j++) {
            var cr = spans[j];
            t.AddSpan(name, cr.row, cr.col, cr.rowCount, cr.colCount, sheetArea);
        }
    }

    function doSelectionsFromJSON(spreadObject, sheetName, selections) {
        if (!selections || !spreadObject || !sheetName) {
            return;
        }

        var t = spreadObject, name = sheetName;
        if (selections.selectionPolicy !== undefined && selections.selectionPolicy !== null) {
            t.SetSelectionPolicy(name, selections.selectionPolicy);
        }
        if (selections.selectionUnit !== undefined && selections.selectionUnit !== null) {
            t.SetSelectionUnit(name, selections.selectionUnit);
        }
        for (var i = 0; i < selections.length; i++) {
            var cr  = selections[i];
            t.AddSelection(name, cr.row, cr.col, cr.rowCount, cr.colCount);
        }

    }

    function doDataFromJSON(spreadObject, sheetName, jsonData, sheetArea) {
        if (!jsonData || !spreadObject || !sheetName) {
            return;
        }

        var t = spreadObject, name = sheetName;
        var rowCount = jsonData.rowCount;
        var colCount = jsonData.colCount;

        //data
        var data = jsonData.dataTable;
        if (data) {
            var dm = new GrapeCity.UI._GcSheetModel(rowCount, colCount);
            dm.dataTable = data;

            var r = dm.nextNonNullRow(-1);
            while (r >= 0) {
                var c = dm.nextNonNullColumn(r, -1);
                while (c >= 0) {
                    var node = dm.getNode(r, c);
                    if (node) {
                        doNodeDataFromJSON(t, name, r, c, node, sheetArea);
                    }
                    c = dm.nextNonNullColumn(r, c);
                }
                r = dm.nextNonNullRow(r);
            }
        }

        //row data
        var rowData = jsonData._rowDataArray;
        if (rowData) {
            for (var r = 0; r < rowCount; r++) {
                if (rowData.hasOwnProperty(r) && rowData[r]) {
                    doNodeDataFromJSON(t, name, r, -1, rowData[r], sheetArea);
                }
            }
        }

        //column data
        var colData = jsonData._columnDataArray;
        if (colData) {
            for (var c = 0; c < colCount; c++) {
                if (colData.hasOwnProperty(c) && colData[c]) {
                    doNodeDataFromJSON(t, name, -1, c, colData[c], sheetArea);
                }
            }
        }

        //default style
        var defDataNode = jsonData._defaultDataNode;
        if (defDataNode) {
            if (typeof(defDataNode.style) !== const_undefined) {
                t.SetDefaultStyle(name, defDataNode.style, sheetArea);
            }
        }
    }

    function doNodeDataFromJSON(spreadObject, sheetName, row, col, node, sheetArea) {
        if (!node || !spreadObject || !sheetName) {
            return;
        }

        var t = spreadObject, name = sheetName;
        var r = row, c = col;
        //sparklines
        if (node.sparkline && sheetArea === GrapeCity.UI.SheetArea.viewport) {
            var x = node.sparkline;
            var setting = new GrapeCity.UI.SparklineSetting(x.setting);
            t.SetSparkline(name, x.row, x.col, x.data, x.orientation, x.type, setting, x.axisReference, x.axisOrientation);
        }
        //value
        if (typeof(node.value) !== const_undefined) {
            t.SetValue(name, r, c, node.value, sheetArea);
        }
        //style
        if (typeof(node.style) !== const_undefined) {
            t.SetStyle(name, r, c, node.style, sheetArea);
        }
        //formual
        if (typeof(node.formula) !== const_undefined && sheetArea === GrapeCity.UI.SheetArea.viewport) {
            t.SetFormula(name, r, c, node.formula);
        }
    }

    function convertKeyCode(keyCode) {
        var result = 0;
        var Key = GrapeCity.UI.Key;
        switch (keyCode) {
            case Key.left:
                result = 14;
                break;
            case Key.right:
                result = 16;
                break;
            case Key.up:
                result = 15;
                break;
            case Key.down:
                result = 17;
                break;
            case Key.tab:
                result = 2;
                break;
            case Key.enter:
                result = 3;
                break;
            case Key.shift:
                result = 4;
                break;
            case Key.ctrl:
                result = 5;
                break;
            case Key.space:
                result = 9;
                break;
            case Key.altkey:
                result = 6;
                break;
            case Key.home:
                result = 13;
                break;
            case Key.end:
                result = 12;
                break;
            case Key.pup:
                result = 10;
                break;
            case Key.pdn:
                result = 11;
                break;
            case Key.backspace:
                result = 1;
                break;
            case Key.del:
                result = 19;
                break;
            case Key.esc:
                result = 8;
                break;
            case Key.c:
                result = 32;
                break;
            case Key.v:
                result = 51;
                break;
            case Key.x:
                result = 53;
                break;
            case Key.z:
                result = 55;
                break;
            case Key.y:
                result = 54;
                break;
        }
        if (result === 0) {
            var aCode = "a".charCodeAt(0);
            var zCode = "z".charCodeAt(0);
            var ACode = "A".charCodeAt(0);
            var ZCode = "Z".charCodeAt(0);
            if (aCode <= keyCode && keyCode <= zCode) {
                result = 30 + keyCode - aCode;
            } else if (ACode <= keyCode && keyCode <= ZCode) {
                result = 30 + keyCode - ACode;
            }
        }
        return result;
    }

    //</editor-fold>

    //<editor-fold desc="GcSpread">
    (function (spreadType) {
        // override gcspread
        spreadType.prototype.attachSpreadsheetObject = function (spreadsheetObject) {
            if(!spreadsheetObject) {
                return;
            }

            var self = this;

            self.spreadsheetObject = spreadsheetObject;

            self._doResize();

            spreadsheetObject.ActiveSheetChanging = function (sender, args) {
                self.onActiveSheetChanging.call(self, args);
            };

            spreadsheetObject.ActiveSheetChanged = function (sender, args) {
                self.onActiveSheetChanged.call(self, args);
            };

            spreadsheetObject.CellClick = function (sender, args) {
                self.onCellClick.call(self, args);
            };

            spreadsheetObject.CellDoubleClick = function (sender, args) {
                self.onCellDoubleClick.call(self, args);
            };

            spreadsheetObject.InvalidOperation = function (sender, args) {
                self.onInvalidOperation.call(self, args);
            };

            spreadsheetObject.RowHeightChanging = function (sender, args) {
                self.onRowHeightChanging.call(self, args);
            };

            spreadsheetObject.RowHeightChanged = function (sender, args) {
                self.onRowHeightChanged.call(self, args);
            };

            spreadsheetObject.ColumnWidthChanging = function (sender, args) {
                self.onColumnWidthChanging.call(self, args);
            };

            spreadsheetObject.ColumnWidthChanged = function (sender, args) {
                self.onColumnWidthChanged.call(self, args);
            };

            spreadsheetObject.ClipboardChanging = function (sender, args) {
                self.onClipboardChanging.call(self, args);
            };

            spreadsheetObject.ClipboardChanged = function (sender, args) {
                self.onClipboardChanged.call(self, args);
            };

            spreadsheetObject.ClipboardPasting = function (sender, args) {
                self.onClipboardPasting.call(self, args);
            };

            spreadsheetObject.ClipboardPasted = function (sender, args) {
                self.onClipboardPasted.call(self, args);
            };

            spreadsheetObject.EnterCell = function (sender, args) {
                self.onEnterCell.call(self, args);
            };

            spreadsheetObject.LeaveCell = function (sender, args) {
                self.onLeaveCell.call(self, args);
            };

            spreadsheetObject.SelectionChanging = function (sender, args) {
                self.onSelectionChanging.call(self, args);
            };

            spreadsheetObject.SelectionChanged = function (sender, args) {
                self.onSelectionChanged.call(self, args);
            };

            spreadsheetObject.EditStarting = function (sender, args) {
                self.onEditStarting.call(self, args);
            };

            spreadsheetObject.EditChange = function (sender, args) {
                self.onEditChange.call(self, args);
            };

            spreadsheetObject.EditEnd = function (sender, args) {
                self.onEditEnd.call(self, args);
            };

            spreadsheetObject.ValueChanged = function (sender, args) {
                self.onValueChanged.call(self, args);
            };

            spreadsheetObject.DragDropBlock = function (sender, args) {
                self.onDragDropBlock.call(self, args);
            };

            spreadsheetObject.DragDropBlockCompleted = function (sender, args) {
                self.onDragDropBlockCompleted.call(self, args);
            };

            spreadsheetObject.SheetTabClick = function (sender, args) {
                self.onSheetTabClick.call(self, args);
            };

            spreadsheetObject.SheetTabDoubleClick = function (sender, args) {
                self.onSheetTabDoubleClick.call(self, args);
            };

            spreadsheetObject.ValidationError = function (sender, args) {
                self.onValidationError.call(self, args);
            };

            spreadsheetObject.LeftColumnChanged = function (sender, args) {
                self.onLeftColumnChanged.call(self, args);
            };

            spreadsheetObject.TopRowChanged = function (sender, args) {
                self.onTopRowChanged.call(self, args);
            };

            spreadsheetObject.UserZooming = function (sender, args) {
                self.onUserZooming.call(self, args);
            };

            spreadsheetObject.UserFormulaEntered = function (sender, args) {
                self.onUserFormulaEntered.call(self, args);
            };

            spreadsheetObject.RangeGroupStateChanging = function (sender, args) {
                self.onRangeGroupStateChanging.call(self, args);
            };

            spreadsheetObject.RangeGroupStateChanged = function (sender, args) {
                self.onRangeGroupStateChanged.call(self, args);
            };

            spreadsheetObject.RangeFiltering = function (sender, args) {
                self.onRangeFiltering.call(self, args);
            };

            spreadsheetObject.RangeFiltered = function (sender, args) {
                self.onRangeFiltered.call(self, args);
            };

            spreadsheetObject.RangeSorting = function (sender, args) {
                self.onRangeSorting.call(self, args);
            };

            spreadsheetObject.RangeSorted = function (sender, args) {
                self.onRangeSorted.call(self, args);
            };

            spreadsheetObject.DragFillBlock = function (sender, args) {
                self.onDragFillBlock.call(self, args);
            };

            spreadsheetObject.DragFillBlockCompleted = function (sender, args) {
                self.onDragFillBlockCompleted.call(self, args);
            };

            spreadsheetObject.CellDataChanged = function (sender, args) {
                self.onCellDataChanged.call(self, args);
            };

            spreadsheetObject.RowDataChanged = function (sender, args) {
                self.onRowDataChanged.call(self, args);
            };

            spreadsheetObject.ColumnDataChanged = function (sender, args) {
                self.onColumnDataChanged.call(self, args);
            };

            spreadsheetObject.SpanModelChanged = function (sender, args) {
                self.onSpanModelChanged.call(self, args);
            };

            spreadsheetObject.RangeGroupDataChanged = function (sender, args) {
                self.onRangeGroupDataChanged.call(self, args);
            };

            spreadsheetObject.WorksheetPropertyChanged = function (sender, args) {
                self.onWorksheetPropertyChanged.call(self, args);
            };

            spreadsheetObject.WorkbookPropertyChanged = function (sender, args) {
                self.onWorkbookPropertyChanged.call(self, args);
            };

            //TODO: add for more for spreadsheetObject

            //work around for sample, after attached spread object then notify sample client to set its code.
            self._trigger("SpreadsheetObjectLoaded");
        };

        spreadType.prototype.onActiveSheetChanging = function (args) {
            var oldSheet = this.getSheetFromName(args.OldSheetName);
            var newSheet = this.getSheetFromName(args.NewSheetName);
            var eArg = {
                oldSheet:oldSheet,
                newSheet:newSheet,
                cancel:false
            };
            this._trigger(GrapeCity.UI.Events.ActiveSheetChanging, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onActiveSheetChanged = function (args) {
            var oldSheet = this.getSheetFromName(args.OldSheetName);
            var newSheet = this.getSheetFromName(args.NewSheetName);
            this._trigger(GrapeCity.UI.Events.ActiveSheetChanged,
                {
                    oldSheet:oldSheet,
                    newSheet:newSheet
                }
            );
        };

        spreadType.prototype.onCellClick = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.CellClick,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    sheetArea:args.SheetArea,
                    row:args.Row,
                    col:args.Column
                }
            );
        };

        spreadType.prototype.onCellDoubleClick = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.CellDoubleClick, {
                sheet:sheet,
                sheetName:sheet._name,
                sheetArea:args.SheetArea,
                row:args.Row,
                col:args.Column
            });
        };

        spreadType.prototype.onInvalidOperation = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.InvalidOperation,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    message:args.Message
                }
            );
        };

        spreadType.prototype.onRowHeightChanging = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                rowList:args.RowList,
                header:args.Header,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.RowHeightChanging, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onRowHeightChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.RowHeightChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    rowList:args.RowList,
                    header:args.Header
                }
            );
        };

        spreadType.prototype.onColumnWidthChanging = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                colList:args.ColumnList,
                header:args.Header,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.ColumnWidthChanging, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onColumnWidthChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.ColumnWidthChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    colList:args.ColumnList,
                    header:args.Header
                }
            );
        };

        spreadType.prototype.onClipboardChanging = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                copyData:args.CopyData,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.ClipboardChanging, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onClipboardChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.ClipboardChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    copyData:args.CopyData
                });
        };

        spreadType.prototype.onClipboardPasting = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                cellRange:convertToRange(args.CellRange),
                pastOption:args.PastOption,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.ClipboardPasting, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onClipboardPasted = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.ClipboardPasted,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    cellRange:convertToRange(args.CellRange),
                    pastOption:args.PastOption
                }
            );
        };

        spreadType.prototype.onEnterCell = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.EnterCell,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    row:args.Row,
                    col:args.Column
                });
        };

        spreadType.prototype.onLeaveCell = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                row:args.Row,
                col:args.Column,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.LeaveCell, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onSelectionChanging = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var t = this.spreadsheetObject;
            if (t) t.SuspendUpdating();
            try {
                var oldRanges = convertToRanges(args.OldSelections);
                var newRanges = convertToRanges(args.NewSelections);
                var sheetType = GrapeCity.UI.GcSheet;
                bindToBaseCall(sheetType, sheet, "clearSelection")();
                if (newRanges) {
                    for (var i = 0; i < newRanges.length; i++) {
                        var cr = newRanges[i];
                        bindToBaseCall(sheetType, sheet, "addSelection")(cr.row, cr.col, cr.rowCount, cr.colCount);
                    }
                }
            } finally {
                if (t) t.ResumeUpdating();
            }

            //fixed SH issue, when clearselection, it will set activecell to (0,0)
            sheet._activeRowIndex = args.ActiveRowIndex;
            sheet._activeColIndex = args.ActiveColumnIndex;

            sheet._trigger(GrapeCity.UI.Events.SelectionChanging,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    oldSelections:oldRanges,
                    newSelections:newRanges
                }
            );
        };

        spreadType.prototype.onSelectionChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.SelectionChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name
                }
            );
        };

        spreadType.prototype.onEditStarting = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                row:args.Row,
                col:args.Column,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.EditStarting, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onEditChange = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.EditChange,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    row:args.Row,
                    col:args.Column
                }
            );
        };

        spreadType.prototype.onEditEnd = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.EditEnd,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    row:args.Row,
                    col:args.Column
                }
            );
        };

        spreadType.prototype.onDragDropBlock = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                fromRow:args.FromRow,
                fromCol:args.FromColumn,
                toRow:args.ToRow,
                toCol:args.ToColumn,
                rowCount:args.RowCount,
                colCount:args.ColumnCount,
                copy:args.Copy,
                insert:args.Insert,
                copyOption:args.CopyOption,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.DragDropBlock, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onDragDropBlockCompleted = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var extent = new GrapeCity.UI.UndoRedo.DragDropExtent(
                args.FromRow
                , args.FromColumn
                , args.ToRow
                , args.ToColumn
                , args.RowCount
                , args.ColumnCount
            );

            var t = this.spreadsheetObject;
            if (t) t.SuspendUpdating();
            try {
                var action = new GrapeCity.UI.UndoRedo.DragDropUndoAction(sheet, extent, args.Copy, args.Insert, args.CopyOption);
                action.execute(sheet);
            } finally {
                if (t) t.ResumeUpdating();
            }

            sheet._trigger(GrapeCity.UI.Events.DragDropBlockCompleted, {
                sheet:sheet,
                sheetName:sheet._name,
                fromRow:args.FromRow,
                fromCol:args.FromColumn,
                toRow:args.ToRow,
                toCol:args.ToColumn,
                rowCount:args.RowCount,
                colCount:args.ColumnCount,
                copy:args.Copy,
                insert:args.Insert,
                copyOption:args.CopyOption
            });
        };

        spreadType.prototype.onSheetTabClick = function (args) {
            if (args.SheetTabIndex === -1) { //new tab
                this._trigger(GrapeCity.UI.Events.SheetTabClick,
                    {
                        sheet:null,
                        sheetName:null,
                        sheetTabIndex:-1
                    }
                );
                var index = this.sheets ? this.sheets.length : 0;
                bindToBaseCall(spreadType, this, "addSheet")(index);

                //Fixed issue: sx, sh rename new worksheet policy is not same.
                if (this.spreadsheetObject) {
                    var t = this.spreadsheetObject;
                    var addedSheet = this.sheets[index];
                    if (addedSheet) {
                        t.SetNameFromJson(index, addedSheet.getName());
                        t.SetRowCount(addedSheet.getName(), addedSheet.getRowCount(), GrapeCity.UI.SheetArea.viewport);
                        t.SetColumnCount(addedSheet.getName(), addedSheet.getColumnCount(), GrapeCity.UI.SheetArea.viewport);
                    }
                }
                //
            } else {
                var sheet = this.getSheetFromName(args.SheetName);
                if (!sheet) return;

                this._trigger(GrapeCity.UI.Events.SheetTabClick,
                    {
                        sheet:sheet,
                        sheetName:sheet._name,
                        sheetTabIndex:args.SheetTabIndex
                    }
                );
            }
        };

        spreadType.prototype.onSheetTabDoubleClick = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            this._trigger(GrapeCity.UI.Events.SheetTabDoubleClick,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    sheetTabIndex:args.SheetTabIndex
                }
            );
        };

        spreadType.prototype.onValidationError = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var dv = sheet.getDataValidator(args.Row, args.Column);
            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                row:args.Row,
                col:args.Column,
                validator:dv,
                validationResult:args.ValidationResult
            };

            sheet._trigger(GrapeCity.UI.Events.ValidationError, eArg);
            args.ValidationResult = eArg.validationResult;
        };

        spreadType.prototype.onLeftColumnChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.LeftColumnChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    oldLeftCol:args.OldIndex,
                    newLeftCol:args.NewIndex
                }
            );
        };

        spreadType.prototype.onTopRowChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.TopRowChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    oldTopRow:args.OldIndex,
                    newTopRow:args.NewIndex
                }
            );
        };

        spreadType.prototype.onUserZooming = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.UserZooming,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    oldZoomFactor:args.OldZoomFactor,
                    newZoomFactor:args.NewZoomFactor
                }
            );
        };

        spreadType.prototype.onUserFormulaEntered = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.UserFormulaEntered,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    row:args.Row,
                    col:args.Column,
                    formula:args.Formula
                }
            );
        };

        spreadType.prototype.onRangeGroupStateChanging = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                isRowGroup:args.IsRowGroup,
                index:args.Index,
                level:args.Level,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.RangeGroupStateChanging, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onRangeGroupStateChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.RangeGroupStateChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    isRowGroup:args.IsRowGroup,
                    index:args.Index,
                    level:args.Level
                }
            );
        };

        spreadType.prototype.onRangeFiltering = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                col:args.Column,
                filterValues:args.FilterValues,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.RangeFiltering, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onRangeFiltered = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.RangeFiltered,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    col:args.Column,
                    filterValues:args.FilterValues
                }
            );
        };

        spreadType.prototype.onRangeSorting = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                col:args.Column,
                ascending:args.Ascending,
                cancel:false
            };

            sheet._trigger(GrapeCity.UI.Events.RangeSorting, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onRangeSorted = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.RangeSorted,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    col:args.Column,
                    ascending:args.Ascending
                }
            );
        };

        spreadType.prototype.onDragFillBlock = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var eArg = {
                sheet:sheet,
                sheetName:sheet._name,
                fillRange:convertToRange(args.FillRange),
                autoFillType:args.AutoFillType,
                fillDirection:args.FillDirection,
                cancel:false
            };
            sheet._trigger(GrapeCity.UI.Events.DragFillBlock, eArg);
            args.Cancel = eArg.cancel;
        };

        spreadType.prototype.onDragFillBlockCompleted = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.DragFillBlockCompleted,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    fillRange:convertToRange(args.FillRange),
                    autoFillType:args.AutoFillType,
                    fillDirection:args.FillDirection
                }
            );
        };

        spreadType.prototype.onValueChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            sheet._trigger(GrapeCity.UI.Events.ValueChanged,
                {
                    sheet:sheet,
                    sheetName:sheet._name,
                    row:args.Row,
                    col:args.Column
                }
            );
        };

        //<editor-fold desc="For Update SH Data">
        spreadType.prototype.onRowDataChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var sheetType = GrapeCity.UI.GcSheet;
            var sheetArea = args.SheetArea;
            var values = args.Values;
            var row = args.Row;
            var rowCount = args.RowCount;
            var type = args.Type;

            if (type === 0) { //Updated
                if (args.Values && args.Values.length === rowCount) {
                    for (var i = 0; i < rowCount; i++) {
                        if (args.PropertyName === "Height") {
                            bindToBaseCall(sheetType, sheet, "setRowHeight")(row + i, values[i], sheetArea);
                        }
                    }
                }
            } else if (type === 1) { //RowsAdded
                //todo: as needed
            } else if (type === 2) { //RowsRemoved
                //todo: as needed
            }
        };

        spreadType.prototype.onColumnDataChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var sheetType = GrapeCity.UI.GcSheet;
            var sheetArea = args.SheetArea;
            var values = args.Values;
            var col = args.Column;
            var colCount = args.ColumnCount;
            var type = args.Type;

            if (type === 0) {
                if (args.Values && args.Values.length === colCount) {
                    for (var i = 0; i < colCount; i++) {
                        if (args.PropertyName === "Width") {
                            bindToBaseCall(sheetType, sheet, "setColumnWidth")(col + i, values[i], sheetArea);
                        }
                    }
                }
            } else if (type === 3) { //ColumnsAdded
                //todo: as needed
            } else if (type === 4) { //ColumnsRemoved
                //todo: as needed
            }
        };

        spreadType.prototype.onCellDataChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var sheetType = GrapeCity.UI.GcSheet;
            var row = args.Row;
            var col = args.Column;
            var sheetArea = args.SheetArea;
            var value = args.Value;

            if (args.PropertyName === "Value") {
                bindToBaseCall(sheetType, sheet, "setValue")(row, col, value, sheetArea);
                if (sheetArea === GrapeCity.UI.SheetArea.viewport) {
                    bindToBaseCall(sheetType, sheet, "setFormula")(row, col, args.Formula);
                }
            } else if (args.PropertyName === "Formula") {
                bindToBaseCall(sheetType, sheet, "setFormula")(row, col, value);
            } else if (args.PropertyName === "[StyleInfo]" || args.PropertyName === "Style") {
                bindToBaseCall(sheetType, sheet, "setStyle")(row, col, convertToStyle(value), sheetArea);
            } else if (args.PropertyName === "Sparkline") {
                if (value) {
                    bindToBaseCall(sheetType, sheet, "setSparkline")(
                        row
                        , col
                        , convertToRange(value.DataRange)
                        , value.DataOrientation
                        , value.Type
                        , convertToSparklineSetting(value.Setting)
                        , convertToRange(value.DateAxisRange)
                        , value.DateAxisOrientation
                    );
                } else {
                    bindToBaseCall(sheetType, sheet, "removeSparkline")(row, col);
                }
            }
        };

        spreadType.prototype.onSpanModelChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var spanModel = sheet._getSpanModel(args.SheetArea);
            if (!spanModel) {
                return;
            }

            var row = args.Row;
            var col = args.Column;
            var rowCount = args.RowCount;
            var colCount = args.ColumnCount;
            if (args.Type === 0) { // SpanAdded
                spanModel.clear(row, col, rowCount, colCount);
                var cr = new GrapeCity.UI.Range(row, col, rowCount, colCount);
                spanModel.push(cr);
            } else if (args.Type === 1) { //SpanRemoved
                spanModel.clear(row, col, rowCount, colCount);
            } else if (args.Type === 2 || args.Type === 3) { //2:SpanUpdated, 3:ModelUpdated
                spanModel.clear(-1, -1, -1, -1);
                var spans = convertToRanges(args.Spans);
                if (spans) {
                    for (var i = 0; i < spans.length; i++) {
                        spanModel.push(spans[i]);
                    }
                }
            }
        };

        spreadType.prototype.onRangeGroupDataChanged = function (args) {
            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            //update data
            if (!args.GroupInfos
                || (args.IsRowGroup && !sheet.rowRangeGroup)
                || (!args.IsRowGroup && !sheet.colRangeGroup)) {
                return;
            }
            var infos = args.GroupInfos;
            var group;
            if (args.IsRowGroup) {
                group = sheet.rowRangeGroup;
            } else {
                group = sheet.colRangeGroup;
            }
            var groupType = GrapeCity.UI.RangeGroup;
            for (var i = 0; i < infos.length; i++) {
                bindToBaseCall(groupType, group, "setCollapsed")(infos[i].SummaryIndex, infos[i].Collapsed);
            }
        };

        spreadType.prototype.onWorksheetPropertyChanged = function (args) {
            //handle sheet name changed
            if (args.PropertyName === "Name") {
                if (args.SheetIndex > 0 && this.sheets) {
                    var sh = this.sheets[args.SheetIndex];
                    if (sh) {
                        sh.setName(args.Value);
                    }
                }
                return;
            }

            var sheet = this.getSheetFromName(args.SheetName);
            if (!sheet) {
                return;
            }

            var p = args.PropertyName;
            var v = args.Value;

            if (p === "ActiveRowIndex") {
                sheet._activeRowIndex = v;
            } else if (p === "ActiveColumnIndex") {
                sheet._activeColIndex = v;
            } else if (p === "ActiveCell") {
                sheet._activeRowIndex = v.Row;
                sheet._activeColIndex = v.Column;
            } else if (p === "Name") {
                sheet.setName(v);
            } else if (p === "DefaultRowHeight") {
                sheet.defaults.rowHeight = v;
            } else if (p === "DefaultColumnWidth") {
                sheet.defaults.colWidth = v;
            } else if (p === "DefaultRowHeaderColumnWidth") {
                sheet.defaults.rowHeaderColWidth = v;
            } else if (p === "DefaultColumnHeaderRowHeight") {
                sheet.defaults.colHeaderRowHeight = v;
            } else if (p === "ZoomFactor") {
                sheet.zoom(v);
            }
            //todo
        };

        spreadType.prototype.onWorkbookPropertyChanged = function (args) {
            var p = args.PropertyName;
            var v = args.Value;

            if (p === "ActiveSheetIndex") {
                this._activeSheetIndex = v;
            }
            //todo
        };
        //</editor-fold>

        subclass(spreadType, "addSheet", function (index, sheet) {
            bindToBaseCall(spreadType, this, "addSheet")(index, sheet);

            if (this.spreadsheetObject) {
                if (arguments.length <= 0) { // no sheet provided
                    index = this.spreadsheetObject.GetSheetCount();
                }
                var addedSheet = this.sheets[index];
                if (addedSheet) {
                    this.spreadsheetObject.AddSheet(index, addedSheet.getName(), addedSheet.getRowCount(), addedSheet.getColumnCount());
                }
                if (arguments.length >= 2) { // have both index and sheet
                    //TODO: need sync data from sheet to new SX spreadsheet
                }
            }
        });

        subclass(spreadType, "addCustomName", function (name, formula, baseRow, baseCol) {
            bindToBaseCall(spreadType, this, "addCustomName")(name, formula, baseRow, baseCol);

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.AddCustomName(name, formula, baseRow, baseCol);
            }
        });

        subclass(spreadType, "removeCustomName", function (name) {
            bindToBaseCall(spreadType, this, "removeCustomName")(name);

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.RemoveCustomName(name);
            }
        });

        subclass(spreadType, "clearCustomNames", function () {
            bindToBaseCall(spreadType, this, "clearCustomNames")();

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.ClearCustomNames();
            }
        });

        subclass(spreadType, "setActiveSheetIndex", function (index) {
            bindToBaseCall(spreadType, this, "setActiveSheetIndex")(index);

            if (this.spreadsheetObject) {
                this.spreadsheetObject.SetActiveSheetIndex(index);
            }
        });
        subclass(spreadType, "_setActiveSheetImp", function (sheet) {
            if (!this.spreadsheetObject) {
                bindToBaseCall(spreadType, this, "_setActiveSheetImp")(sheet);
            }
        });

        subclass(spreadType, "fromJSON", function (spreadData) {
            var t = this.spreadsheetObject ? this.spreadsheetObject : null;
            try {
                if (t) t.SuspendUpdating();
                bindToBaseCall(spreadType, this, "fromJSON")(spreadData);
            } finally {
                if (t) t.ResumeUpdating();
            }

            // do custom action
            if (t) {
                doSpreadObjectFromJSON(t, spreadData);
            }
        });

        subclass(spreadType, "allowUserZoom", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.AllowUserZoom = value;
                }
            }

            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "allowUserZoom")(value);
            } else {
                return bindToBaseCall(spreadType, this, "allowUserZoom")();
            }
        });

        subclass(spreadType, "tabStripVisible", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetTabStripVisible(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "tabStripVisible")(value);
            } else {
                return bindToBaseCall(spreadType, this, "tabStripVisible")();
            }
        });

        subclass(spreadType, "tabEditable", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetTabEditable(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "tabEditable")(value);
            } else {
                return bindToBaseCall(spreadType, this, "tabEditable")();
            }
        });

        subclass(spreadType, "newTabVisible", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetNewTabVisible(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "newTabVisible")(value);
            } else {
                return bindToBaseCall(spreadType, this, "newTabVisible")();
            }
        });

        subclass(spreadType, "removeSheet", function (index) {
            bindToBaseCall(spreadType, this, "removeSheet")(index);

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.RemoveSheet(index);
            }
        });

        subclass(spreadType, "clearSheets", function () {
            bindToBaseCall(spreadType, this, "clearSheets")();

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.ClearSheets();
            }
        });

        subclass(spreadType, "setSheetCount", function (count) {
            bindToBaseCall(spreadType, this, "setSheetCount")(count);

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.SetSheetCount(count);
            }
        });

        subclass(spreadType, "referenceStyle", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetSpreadReferenceStyle(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "referenceStyle")(value);
            } else {
                return bindToBaseCall(spreadType, this, "referenceStyle")();
            }
        });

        subclass(spreadType, "allowUndo", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetAllowUndo(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "allowUndo")(value);
            } else {
                return bindToBaseCall(spreadType, this, "allowUndo")();
            }
        });

        subclass(spreadType, "canUserDragDrop", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetCanUserDragDrop(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "canUserDragDrop")(value);
            } else {
                return bindToBaseCall(spreadType, this, "canUserDragDrop")();
            }
        });

        subclass(spreadType, "canUserDragFill", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.SetCanUserDragFill(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "canUserDragFill")(value);
            } else {
                return bindToBaseCall(spreadType, this, "canUserDragFill")();
            }
        });

        subclass(spreadType, "setTabStripRatio", function (tabStripRatio, skipRefreshScrollbar) {
            var ratio;
            if (isNaN(ratio = parseFloat(tabStripRatio))) {
                throw "ArgumentException";
            }
            if (ratio < 0) {
                this._tabStripRatio = 0;
            } else if (ratio > 1) {
                this._tabStripRatio = 1;
            } else {
                this._tabStripRatio = ratio;
            }
            this._tabStripRatioUserSet = this._tabStripRatio;//for getTabStripRatio

            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.SetTabStripRatio(this.getTabStripRatio());
            }
        });

        subclass(spreadType, "repaint", function () {
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                t.Invalidate();
            }
        });

        subclass(spreadType, "canUserEditFormula", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.AllowUserFormula = value;
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "canUserEditFormula")(value);
            } else {
                return bindToBaseCall(spreadType, this, "canUserEditFormula")();
            }
        });

        subclass(spreadType, "startSheetIndex", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                var t = this.spreadsheetObject;
                if (arguments.length > 0) {
                    t.StartSheetIndex = value;
                    return this;
                } else {
                    return t.StartSheetIndex;
                }
            }
        });

        subclass(spreadType, "_dispose", function () {
            //Silverlight have itself dispose policy, not care in javascript
        });

        subclass(spreadType, "highlightInvalidData", function (value) {
            // do custom action
            if (this.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.spreadsheetObject;
                    t.HighlightInvalidData = value;
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(spreadType, this, "highlightInvalidData")(value);
            } else {
                return bindToBaseCall(spreadType, this, "highlightInvalidData")();
            }
        });
    })(GrapeCity.UI.GcSpread);
    //</editor-fold>

    //<editor-fold desc="GcSheet">
    (function (sheetType) {
        // override gcssheet
        subclass(sheetType, "setStyle", function (row, col, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setStyle")(row, col, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }

                var t = this.parent.spreadsheetObject;
                t.SetStyle(this.getName(), row, col, value, sheetArea);
            }
        });

        subclass(sheetType, "setValue", function (row, col, value, sheetArea, ignoreRecalc) {
            bindToBaseCall(sheetType, this, "setValue")(row, col, value, sheetArea, ignoreRecalc);

            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }

                var t = this.parent.spreadsheetObject;
                var v = value;
                if (value instanceof Number) {
                    v = value.valueOf();
                } else if (value instanceof Date) {
                    v = "/Date(" + value.valueOf() + ")/";
                }
                t.SetValue(this.getName(), row, col, v, sheetArea);
            }
        });

        subclass(sheetType, "setText", function (row, col, text, sheetArea) {
            bindToBaseCall(sheetType, this, "setText")(row, col, text, sheetArea);

            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }

                var t = this.parent.spreadsheetObject;
                t.SetText(this.getName(), row, col, text, sheetArea);
            }
        });

        subclass(sheetType, "setFormula", function (row, col, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setFormula")(row, col, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (sheetArea === GrapeCity.UI.SheetArea.viewport || sheetArea === null || sheetArea === undefined) {
                    t.SetFormula(this.getName(), row, col, value);
                }
            }
        });

        subclass(sheetType, "addCustomName", function (name, formula, baseRow, baseCol) {
            bindToBaseCall(sheetType, this, "addCustomName")(name, formula, baseRow, baseCol);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AddCustomName(this.getName(), name, formula, baseRow, baseCol);
            }
        });

        subclass(sheetType, "removeCustomName", function (name) {
            bindToBaseCall(sheetType, this, "removeCustomName")(name);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.RemoveCustomName(this.getName(), name);
            }
        });

        subclass(sheetType, "clearCustomNames", function () {
            bindToBaseCall(sheetType, this, "clearCustomNames")();

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.ClearCustomNames(this.getName());
            }
        });

        subclass(sheetType, "sortRange", function (row, column, rowCount, columnCount, byRows, sortInfo) {
            var result = bindToBaseCall(sheetType, this, "sortRange")(row, column, rowCount, columnCount, byRows, sortInfo);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                for (var i = 0; i < sortInfo.length;) {
                    var info = sortInfo[i];
                    if (info) {
                        var index = info.index;
                        if ((byRows && (index < column || index >= column + columnCount)) ||
                            (!byRows && (index < row || index >= row + rowCount))) {
                            sortInfo.splice(i, 1);
                        } else {
                            i++;
                        }
                    } else {
                        sortInfo.splice(i, 1);
                    }
                }
                if (sortInfo.length > 0) {
                    t.SortRange(this.getName(), row, column, rowCount, columnCount, byRows, sortInfo);
                }
            }

            return result;
        });

        subclass(sheetType, "fromJSON", function (sheetData) {
            //first forbit to update data to sx
            var t = (this.parent ? this.parent.spreadsheetObject : null);
            try {
                if (t) t.SuspendUpdating();
                bindToBaseCall(sheetType, this, "fromJSON")(sheetData);
            } finally {
                if (t) t.ResumeUpdating();
            }

            //do custom action
            if (t) {
                doSheetObjectFromJSON(t, sheetData);
            }
        });

        // API for invoke from JS
        subclass(sheetType, "addSpan", function (row, col, rowCount, colCount, sheetArea) {
            bindToBaseCall(sheetType, this, "addSpan")(row, col, rowCount, colCount, sheetArea);

            //sync data to spreadsheetObject
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === null || sheetArea === undefined) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                } else if (sheetArea === GrapeCity.UI.SheetArea.corner) {
                    return;
                }
                if (col === -1) {
                    col = 0;
                    colCount = this.getColumnCount(sheetArea);
                }
                if (row === -1) {
                    row = 0;
                    rowCount = this.getRowCount(sheetArea);
                }
                this.parent.spreadsheetObject.AddSpan(this.getName(), row, col, rowCount, colCount, sheetArea);
            }
        });
        subclass(sheetType, "removeSpan", function (row, col, sheetArea) {
            bindToBaseCall(sheetType, this, "removeSpan")(row, col, sheetArea);

            //sync data to spreadsheetObject
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === null || sheetArea === undefined) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                this.parent.spreadsheetObject.RemoveSpan(this.getName(), row, col, sheetArea);
            }
        });

        subclass(sheetType, "setActiveCell", function (row, col, rowViewportIndex, colViewportIndex) {
            bindToBaseCall(sheetType, this, "setActiveCell")(row, col, rowViewportIndex, colViewportIndex);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetActiveCell(this.getName(), row, col);
            }
        });

        subclass(sheetType, "reset", function () {
            bindToBaseCall(sheetType, this, "reset")();
            //set for sync rangegroup data to sx silverlight
            if (this.rowRangeGroup) {
                this.rowRangeGroup._worksheet = this;
                this.rowRangeGroup._isRowGroup = true;
            }
            if (this.colRangeGroup) {
                this.colRangeGroup._worksheet = this;
                this.colRangeGroup._isRowGroup = false;
            }

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.ResetSheet(this.getName());
            }
        });

        subclass(sheetType, "setSparkline", function (row, col, dataRange, dataOrientation, sparklineType, sparklineSetting, dateAxisRange, dateAxisOrientation) {
            var sp = bindToBaseCall(sheetType, this, "setSparkline")(row, col, dataRange, dataOrientation, sparklineType, sparklineSetting, dateAxisRange, dateAxisOrientation);
            sp._worksheet = this;

            //do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetSparkline(this.getName(), row, col, dataRange, dataOrientation, sparklineType, sparklineSetting, dateAxisRange, dateAxisOrientation);
            }
            return sp;
        });

        subclass(sheetType, "removeSparkline", function (row, col) {
            bindToBaseCall(sheetType, this, "removeSparkline")(row, col);

            //do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                this.parent.spreadsheetObject.RemoveSparkline(this.getName(), row, col);
            }
        });

        subclass(sheetType, "groupSparkline", function (sparklines) {
            bindToBaseCall(sheetType, this, "groupSparkline")(sparklines);

            var ret = new Array();
            //do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                for (var i = 0; i < sparklines.length; i++) {
                    var obj = { row:sparklines[i].row, column:sparklines[i].column };
                    ret.push(obj);
                }

                this.parent.spreadsheetObject.GroupSparkline(this.getName(), ret);
            }
        });

        subclass(sheetType, "ungroupSparkline", function (group) {
            //call base
            var sparkline = null;
            if (group._innerList && group._innerList.length > 0) {
                sparkline = group._innerList[0];
            }

            bindToBaseCall(sheetType, this, "ungroupSparkline")(group);

            //do custom action
            if (sparkline && this.parent && this.parent.spreadsheetObject) {
                this.parent.spreadsheetObject.UngroupSparkline(this.getName(), sparkline.row, sparkline.column);
            }
        });

        subclass(sheetType, "referenceStyle", function (value) {
            var ret;
            if (arguments.length > 0) {
                ret = bindToBaseCall(sheetType, this, "referenceStyle")(value);
            } else {
                ret = bindToBaseCall(sheetType, this, "referenceStyle")();
            }

            // do custom action
            if (this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.SetSheetReferenecStyle(this.getName(), value);
                }
            }

            return ret;
        });

        subclass(sheetType, "recalcAll", function () {
            bindToBaseCall(sheetType, this, "recalcAll")();

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.ReCalcAll(this.getName());
            }
        });

        subclass(sheetType, "setName", function (name) {
            var oldName = this.getName();
            bindToBaseCall(sheetType, this, "setName")(name);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetName(oldName, this.getName());
            }
        });

        subclass(sheetType, "allowCellOverflow", function (value) {
            var ret;
            if (arguments.length > 0) {
                ret = bindToBaseCall(sheetType, this, "allowCellOverflow")(value);
            } else {
                ret = bindToBaseCall(sheetType, this, "allowCellOverflow")();
            }

            // do custom action
            if (this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.CanCellOverflow = value;
                }
            }

            return ret;
        });

        subclass(sheetType, "allowUndo", function (value) {
            var ret;
            if (arguments.length > 0) {
                ret = bindToBaseCall(sheetType, this, "allowUndo")(value);
            } else {
                ret = bindToBaseCall(sheetType, this, "allowUndo")();
            }

            // do custom action
            if (this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.SetAllowUndo(value);
                }
            }

            return ret;
        });

        subclass(sheetType, "addRows", function (row, count) {
            bindToBaseCall(sheetType, this, "addRows")(row, count);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AddRows(this.getName(), row, count);
            }
        });

        subclass(sheetType, "deleteRows", function (row, count) {
            bindToBaseCall(sheetType, this, "deleteRows")(row, count);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.DeleteRows(this.getName(), row, count);
            }
        });

        subclass(sheetType, "addColumns", function (col, count) {
            bindToBaseCall(sheetType, this, "addColumns")(col, count);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AddColumns(this.getName(), col, count);
            }
        });

        subclass(sheetType, "deleteColumns", function (col, count) {
            bindToBaseCall(sheetType, this, "deleteColumns")(col, count);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.DeleteColumns(this.getName(), col, count);
            }
        });

        subclass(sheetType, "setFrozenCount", function (rowCount, colCount) {
            bindToBaseCall(sheetType, this, "setFrozenCount")(rowCount, colCount);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetFrozenCount(this.getName(), rowCount, colCount);
            }
        });

        subclass(sheetType, "setRowCount", function (rowCount, sheetArea) {
            bindToBaseCall(sheetType, this, "setRowCount")(rowCount, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                t.SetRowCount(this.getName(), rowCount, sheetArea);
            }
        });

        subclass(sheetType, "setColumnCount", function (colCount, sheetArea) {
            bindToBaseCall(sheetType, this, "setColumnCount")(colCount, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                t.SetColumnCount(this.getName(), colCount, sheetArea);
            }
        });

        subclass(sheetType, "setDefaultStyle", function (style, sheetArea) {
            bindToBaseCall(sheetType, this, "setDefaultStyle")(style, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }

                var t = this.parent.spreadsheetObject;
                t.SetDefaultStyle(this.getName(), style, sheetArea);
            }
        });

        subclass(sheetType, "addSelection", function (row, column, rowCount, columnCount) {
            bindToBaseCall(sheetType, this, "addSelection")(row, column, rowCount, columnCount);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AddSelection(this.getName(), row, column, rowCount, columnCount);
            }
        });

        subclass(sheetType, "clearSelection", function () {
            bindToBaseCall(sheetType, this, "clearSelection")();

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.ClearSelection(this.getName());
            }
        });

        subclass(sheetType, "setRowResizable", function (row, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setRowResizable")(row, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetRowResizable(this.getName(), row, value, sheetArea);
            }
        });

        subclass(sheetType, "setColumnResizable", function (col, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setColumnResizable")(col, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetColumnResizable(this.getName(), col, value, sheetArea);
            }
        });

        subclass(sheetType, "setRowHeight", function (row, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setRowHeight")(row, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetRowHeight(this.getName(), row, value, sheetArea);
            }
        });

        subclass(sheetType, "setRowVisible", function (row, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setRowVisible")(row, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetRowVisible(this.getName(), row, value, sheetArea);
            }
        });

        subclass(sheetType, "setColumnWidth", function (col, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setColumnWidth")(col, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetColumnWidth(this.getName(), col, value, sheetArea);
            }
        });

        subclass(sheetType, "setColumnVisible", function (col, value, sheetArea) {
            bindToBaseCall(sheetType, this, "setColumnVisible")(col, value, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                t.SetColumnVisible(this.getName(), col, value, sheetArea);
            }
        });

        subclass(sheetType, "zoom", function (factor) {
            bindToBaseCall(sheetType, this, "zoom")(factor);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.Zoom(this.getName(), this._zoomFactor);
            }
        });

        subclass(sheetType, "setBorder", function (cellRange, border, option, sheetArea) {
            bindToBaseCall(sheetType, this, "setBorder")(cellRange, border, option, sheetArea);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (sheetArea === undefined || sheetArea === null) {
                    sheetArea = GrapeCity.UI.SheetArea.viewport;
                }
                var t = this.parent.spreadsheetObject;
                var op = 0;
                if (option) {
                    if (option.top) {
                        op |= 1;
                    }
                    if (option.left) {
                        op |= 2;
                    }
                    if (option.right) {
                        op |= 4;
                    }
                    if (option.bottom) {
                        op |= 8;
                    }
                    if (option.outline) {
                        op |= 15;
                    }
                    if (option.innerVertical) {
                        op |= 16;
                    }
                    if (option.innerHorizontal) {
                        op |= 32;
                    }
                    if (option.inside) {
                        op |= 48;
                    }
                    if (option.all) {
                        op |= 63;
                    }
                } else {
                    op = 63;
                }
                t.SetBorder(this.getName(), cellRange, border, op, sheetArea);
            }
        });

        subclass(sheetType, "currentTheme", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    var name = value;
                    if (value instanceof GrapeCity.UI.SpreadTheme) {
                        name = value.name();
                    }
                    t.CurrentThemeName = name;
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "currentTheme")(value);
            } else {
                return bindToBaseCall(sheetType, this, "currentTheme")();
            }
        });

        subclass(sheetType, "clipBoardOptions", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.ClipBoardOptions = value;
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "clipBoardOptions")(value);
            } else {
                return bindToBaseCall(sheetType, this, "clipBoardOptions")();
            }
        });

        subclass(sheetType, "setCsv", function (row, column, text, rowDelimiter, columnDelimiter, flags) {
            bindToBaseCall(sheetType, this, "setCsv")(row, column, text, rowDelimiter, columnDelimiter, flags);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetCsv(this.getName(), row, column, text, rowDelimiter, columnDelimiter, "\"", flags);
            }
        });

        subclass(sheetType, "fillAuto", function (startRange, wholeRange, series) {
            bindToBaseCall(sheetType, this, "fillAuto")(startRange, wholeRange, series);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.FillAuto(this.getName(), startRange, wholeRange, series);
            }
        });

        subclass(sheetType, "fillAutobyDirection", function (startRange, wholeRange, direction) {
            bindToBaseCall(sheetType, this, "fillAutobyDirection")(startRange, wholeRange, direction);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.FillAutoByDirection(this.getName(), startRange, wholeRange, direction);
            }
        });

        subclass(sheetType, "fillLinear", function (startRange, wholeRange, series, step, stop) {
            bindToBaseCall(sheetType, this, "fillLinear")(startRange, wholeRange, series, step, stop);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.FillLinear(this.getName(), startRange, wholeRange, series, step, stop);
            }
        });

        subclass(sheetType, "fillGrowth", function (startRange, wholeRange, series, step, stop) {
            bindToBaseCall(sheetType, this, "fillGrowth")(startRange, wholeRange, series, step, stop);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.FillGrowth(this.getName(), startRange, wholeRange, series, step, stop);
            }
        });

        subclass(sheetType, "fillDate", function (startRange, wholeRange, series, unit, step, stop) {
            bindToBaseCall(sheetType, this, "fillDate")(startRange, wholeRange, series, unit, step, stop);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var v = stop;
                if (stop instanceof Date) {
                    v = stop.toDateString();
                }
                t.FillDate(this.getName(), startRange, wholeRange, series, unit, step, v);
            }
        });

        subclass(sheetType, "clear", function (row, column, rowCount, columnCount, area, type) {
            bindToBaseCall(sheetType, this, "clear")(row, column, rowCount, columnCount, area, type);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (area === undefined || area === null) {
                    area = GrapeCity.UI.SheetArea.viewport;
                }
                if (type === undefined || type === null) {
                    type = 0;
                }
                t.Clear(this.getName(), row, column, rowCount, columnCount, area, type);
            }
        });

        subclass(sheetType, "addKeyMap", function (keyCode, ctrl, shift, alt, action) {
            bindToBaseCall(sheetType, this, "addKeyMap")(keyCode, ctrl, shift, alt, action);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AddKeyMap(convertKeyCode(keyCode), ctrl, shift, alt, action._name);
            }
        });

        subclass(sheetType, "removeKeyMap", function (keyCode, ctrl, shift, alt, action) {
            bindToBaseCall(sheetType, this, "removeKeyMap")(keyCode, ctrl, shift, alt, action);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.RemoveKeyMap(convertKeyCode(keyCode), ctrl, shift, alt);
            }
        });

        subclass(sheetType, "showCell", function (row, col, verticalPosition, horizontalPosition) {
            bindToBaseCall(sheetType, this, "showCell")(row, col, verticalPosition, horizontalPosition);

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var activeSheet = this.parent.getActiveSheet();
                if (activeSheet && this.getName() === activeSheet.getName()) {
                    t.ShowCell(row, col, verticalPosition, horizontalPosition);
                }
            }
        });

        subclass(sheetType, "canUserDragDrop", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.SetCanUserDragDrop(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "canUserDragDrop")(value);
            } else {
                return bindToBaseCall(sheetType, this, "canUserDragDrop")();
            }
        });

        subclass(sheetType, "canUserDragFill", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.SetCanUserDragFill(value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "canUserDragFill")(value);
            } else {
                return bindToBaseCall(sheetType, this, "canUserDragFill")();
            }
        });

        subclass(sheetType, "isEditing", function () {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var activeSheet = this.parent.getActiveSheet();
                if (activeSheet && this.getName() === activeSheet.getName()) {
                    return t.IsEditing();
                }
            }
            return false;
        });

        subclass(sheetType, "startEdit", function (selectAll, defaultText) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (!selectAll) {
                    selectAll = false;
                }
                var activeSheet = this.parent.getActiveSheet();
                if (activeSheet && this.getName() === activeSheet.getName()) {
                    if (arguments.length < 2) {
                        t.StartEdit(selectAll);
                    } else {
                        t.StartEditWithDefaultText(selectAll, defaultText);
                    }
                }
            }
        });

        subclass(sheetType, "endEdit", function (ignoreValueChange) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (!ignoreValueChange) {
                    ignoreValueChange = false;
                }
                var activeSheet = this.parent.getActiveSheet();
                if (activeSheet && this.getName() === activeSheet.getName()) {
                    t.EndEdit(ignoreValueChange);
                }
            }
        });

        subclass(sheetType, "getViewportHeight", function(rowViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = rowViewportIndex - 1;
                return t.GetViewportHeight(this.getName(), vpIndex);
            }
            return 0;
        });

        subclass(sheetType, "getViewportTopRow", function(rowViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = rowViewportIndex - 1;
                return t.GetViewportTopRow(this.getName(), vpIndex);
            }
            return -1;
        });

        subclass(sheetType, "getViewportBottomRow", function(rowViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = rowViewportIndex - 1;
                return t.GetViewportBottomRow(this.getName(), vpIndex);
            }
            return -1;
        });

        subclass(sheetType, "getViewportWidth ", function(colViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = colViewportIndex - 1;
                return t.GetViewportWidth(this.getName(), vpIndex);
            }
            return 0;
        });

        subclass(sheetType, "getViewportLeftColumn", function(colViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = colViewportIndex - 1;
                return t.GetViewportLeftColumn(this.getName(), vpIndex);
            }
            return -1;
        });

        subclass(sheetType, "getViewportRightColumn", function(colViewportIndex) {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var vpIndex = colViewportIndex - 1;
                return t.GetViewportRightColumn(this.getName(), vpIndex);
            }
            return -1;
        });

        subclass(sheetType, "copyTo", function (fromRow, fromColumn, toRow, toColumn, rowCount, columnCount, option) {
            var t;
            if (this.parent && this.parent.spreadsheetObject) {
                t = this.parent.spreadsheetObject;
            }
            try {
                if (t) {
                    t.SuspendUpdating();
                }
                bindToBaseCall(sheetType, this, "copyTo")(fromRow, fromColumn, toRow, toColumn, rowCount, columnCount,
                    option);
            } finally {
                if (t) {
                    t.ResumeUpdating();
                }
            }

            if (t) {
                if (!option) {
                    option = 0;
                }
                t.CopyTo(this.getName(), fromRow, fromColumn, toRow, toColumn, rowCount, columnCount, option);
            }
        });

        subclass(sheetType, "moveTo", function (fromRow, fromColumn, toRow, toColumn, rowCount, columnCount, option) {
            var t;
            if (this.parent && this.parent.spreadsheetObject) {
                t = this.parent.spreadsheetObject;
            }
            try {
                if (t) {
                    t.SuspendUpdating();
                }
                bindToBaseCall(sheetType, this, "moveTo")(fromRow, fromColumn, toRow, toColumn, rowCount, columnCount,
                    option);
            } finally {
                if (t) {
                    t.ResumeUpdating();
                }
            }

            if (t) {
                if (!option) {
                    option = 0;
                }
                t.MoveTo(this.getName(), fromRow, fromColumn, toRow, toColumn, rowCount, columnCount, option);
            }
        });

        subclass(sheetType, "suspendCalcService", function () {
            bindToBaseCall(sheetType, this, "suspendCalcService")();

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SuspendCalcService(this.getName());
            }
        });

        subclass(sheetType, "resumeCalcService", function () {
            bindToBaseCall(sheetType, this, "resumeCalcService")();

            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.ResumeCalcService(this.getName());
            }
        });

        subclass(sheetType, "isPaintSuspended", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (arguments.length > 0) {
                    if (value === true) {
                        t.SuspendAutoRefresh();
                    } else if (value === false) {
                        t.ResumeAutoRefresh();
                    }
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "isPaintSuspended")(value);
            } else {
                return bindToBaseCall(sheetType, this, "isPaintSuspended")();
            }
        });

        subclass(sheetType, "repaint", function () {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.InvalidateSheet(this.getName());
            }
        });

        subclass(sheetType, "rowFilter", function(value){
            if(arguments.length === 0) {
                return bindToBaseCall(sheetType, this, "rowFilter")();
            } else {
                var ret = bindToBaseCall(sheetType, this, "rowFilter")(value);

                if (this.parent && this.parent.spreadsheetObject) {
                    var t = this.parent.spreadsheetObject;
                    t.SetRowFilter(this.getName(), (value ? value.range : null));
                }

                return ret;
            }
        });

        subclass(sheetType, "autoFitColumn", function(column){
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AutoFitColumn(this.getName(), column);
            }
        });

        subclass(sheetType, "autoFitRow", function(row){
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.AutoFitRow(this.getName(), row);
            }
        });

        subclass(sheetType, "setGridlineOptions", function(options) {
            bindToBaseCall(sheetType, this, "setGridlineOptions")(options);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                var color = "", showVerticalGridline = true, showHorizontalGridline = true;
                if (options) {
                    if (options.color) {
                        color = options.color;
                    }
                    if(options.showVerticalGridline !== null && options.showVerticalGridline !== undefined){
                        showVerticalGridline = options.showVerticalGridline;
                    }
                    if(options.showHorizontalGridline !== null && options.showHorizontalGridline !== undefined) {
                        showHorizontalGridline = options.showHorizontalGridline;
                    }
                }
                t.SetGridlineOptions(this.getName(), color, showVerticalGridline, showHorizontalGridline);
            }
        });

        subclass(sheetType, "setRowHeaderVisible", function(visible) {
            bindToBaseCall(sheetType, this, "setRowHeaderVisible")(visible);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetRowHeaderVisible(this.getName(), visible);
            }
        });

        subclass(sheetType, "setColumnHeaderVisible", function(visible) {
            bindToBaseCall(sheetType, this, "setColumnHeaderVisible")(visible);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetColumnHeaderVisible(this.getName(), visible);
            }
        });

        subclass(sheetType, "setRowHeaderAutoText", function(autoText) {
            bindToBaseCall(sheetType, this, "setRowHeaderAutoText")(autoText);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetRowHeaderAutoText(this.getName(), autoText);
            }
        });

        subclass(sheetType, "setColumnHeaderAutoText", function(autoText) {
            bindToBaseCall(sheetType, this, "setColumnHeaderAutoText")(autoText);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetColHeaderAutoText(this.getName(), autoText);
            }
        });

        subclass(sheetType, "setRowHeaderAutoTextIndex", function(autoTextIndex) {
            bindToBaseCall(sheetType, this, "setRowHeaderAutoTextIndex")(autoTextIndex);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetRowHeaderAutoTextIndex(this.getName(), autoTextIndex);
            }
        });

        subclass(sheetType, "setColumnHeaderAutoTextIndex", function(autoTextIndex) {
            bindToBaseCall(sheetType, this, "setColumnHeaderAutoTextIndex")(autoTextIndex);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetColHeaderAutoTextIndex(this.getName(), autoTextIndex);
            }
        });

        subclass(sheetType, "setIsProtected", function(isProtected) {
            bindToBaseCall(sheetType, this, "setIsProtected")(isProtected);

            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                t.SetSheetProtected(this.getName(), isProtected);
            }
        });

        subclass(sheetType, "sheetTabColor", function (value) {
            // do custom action
            if (this.parent && this.parent.spreadsheetObject) {
                if (arguments.length > 0) {
                    var t = this.parent.spreadsheetObject;
                    t.SetSheetTabColor(this.getName(), value);
                }
            }
            if (arguments.length > 0) {
                return bindToBaseCall(sheetType, this, "sheetTabColor")(value);
            } else {
                return bindToBaseCall(sheetType, this, "sheetTabColor")();
            }
        });

        subclass(sheetType, "showRowRangeGroup", function (value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sheetType, this, "showRowRangeGroup")();
            } else {
                if (this.parent && this.parent.spreadsheetObject) {
                    var t = this.parent.spreadsheetObject;
                    t.ShowRowRangeGroup = value;
                }

                return bindToBaseCall(sheetType, this, "showRowRangeGroup")(value);
            }
        });

        subclass(sheetType, "showColumnRangeGroup", function (value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sheetType, this, "showColumnRangeGroup")();
            } else {
                if (this.parent && this.parent.spreadsheetObject) {
                    var t = this.parent.spreadsheetObject;
                    t.ShowColumnRangeGroup = value;
                }

                return bindToBaseCall(sheetType, this, "showColumnRangeGroup")(value);
            }
        });

        subclass(sheetType, "editorStatus", function() {
            if (this.parent && this.parent.spreadsheetObject) {
                var t = this.parent.spreadsheetObject;
                if (this === this.parent.getActiveSheet()) {
                    return t.GetEditorStatus();
                }
            }
            return GrapeCity.UI.EditorStatus.Ready;
        });

        subclass(sheetType, "selectionPolicy", function (value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sheetType, this, "selectionPolicy")();
            } else {
                if (this.parent && this.parent.spreadsheetObject) {
                    var t = this.parent.spreadsheetObject;
                    t.SetSelectionPolicy(this.getName(), value);
                }
                return bindToBaseCall(sheetType, this, "selectionPolicy")(value);
            }
        });

        subclass(sheetType, "selectionUnit", function(value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sheetType, this, "selectionUnit")();
            } else {
                if (this.parent && this.parent.spreadsheetObject) {
                    var t = this.parent.spreadsheetObject;
                    t.SetSelectionUnit(this.getName(), value);
                }
                return bindToBaseCall(sheetType, this, "selectionUnit")(value);
            }
        });
    })(GrapeCity.UI.GcSheet);
    //</editor-fold>

    //<editor-fold desc="Cell">
    (function(cellType){
        subclass(cellType, "clearStyleProperty", function(propertyName) {
            bindToBaseCall(cellType, this, "clearStyleProperty")(propertyName);

            //
            if(this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t  = this.sheet.parent.spreadsheetObject;

                for (var r = this.row; r <= this.row2; r++) {
                    for (var c = this.col; c <= this.col2; c++) {
                        if (this._isValidIndex(r, c)) {
                            var style = this.sheet.getStyle(r, c, this.sheetArea);
                            if(style) {
                                t.SetStyle(this.sheet.getName(), r, c, style, this.sheetArea);
                            }
                        }
                    }
                }
            }
        });

    })(GrapeCity.UI.Cell);
    //</editor-fold>

    //<editor-fold desc="Row">
    (function(rowType){
        subclass(rowType, "clearStyleProperty", function(propertyName){
            bindToBaseCall(rowType, this, "clearStyleProperty")(propertyName);

            //
            if(this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;

                for (var r = this.index; r <= this.index2; r++) {
                    if (this._isValidIndex(r)) {
                        var style = this.sheet.getStyle(r, -1, this.sheetArea);
                        if (style) {
                            t.SetStyle(this.sheet.getName(), r, -1, style, this.sheetArea);
                        }
                    }
                }
            }
        });

    })(GrapeCity.UI.Row);
    //</editor-fold>

    //<editor-fold desc="Column">
    (function(colType){
        subclass(colType, "clearStyleProperty", function(propertyName) {
            bindToBaseCall(colType, this, "clearStyleProperty")(propertyName);

            //
            if(this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;

                for (var c = this.index; c <= this.index2; c++) {
                    if (this._isValidIndex(c)) {
                        var style = this.sheet.getStyle(-1, c, this.sheetArea);
                        if (style) {
                            t.SetStyle(this.sheet.getName(), -1, c, style, this.sheetArea);
                        }
                    }
                }
            }
        });

    })(GrapeCity.UI.Col);

    //</editor-fold>

    //<editor-fold desc="Sparkline">
    (function (sparklineType) {
        subclass(sparklineType, "sparklineType", function (value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sparklineType, this, "sparklineType")();
            }
            else {
                bindToBaseCall(sparklineType, this, "sparklineType")(value);

                if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                    var t = this._worksheet.parent.spreadsheetObject;
                    t.SetSparklineType(this._worksheet.getName(), this.row, this.column, value);
                }
            }
        });

        subclass(sparklineType, "setting", function (value) {
            if (arguments.length === 0) {
                return bindToBaseCall(sparklineType, this, "setting")();
            }
            else {
                bindToBaseCall(sparklineType, this, "setting")(value);

                if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                    var t = this._worksheet.parent.spreadsheetObject;
                    t.SetSparklineSetting(this._worksheet.getName(), this.row, this.column, value);
                }
            }
        });

    })(GrapeCity.UI.Sparkline);
    //</editor-fold>

    //<editor-fold desc="RangeGroup">
    (function (groupType) {
        subclass(groupType, "group", function (index, count) {
            bindToBaseCall(groupType, this, "group")(index, count);

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.Group(this._worksheet.getName(), this._isRowGroup, index, count);
            }
        });

        subclass(groupType, "ungroupRange", function (index, count) {
            bindToBaseCall(groupType, this, "ungroupRange")(index, count);

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.UngroupRange(this._worksheet.getName(), this._isRowGroup, index, count);
            }
        });

        subclass(groupType, "ungroup", function () {
            bindToBaseCall(groupType, this, "ungroup")();

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.Ungroup(this._worksheet.getName(), this._isRowGroup);
            }
        });

        subclass(groupType, "expand", function (level, expand) {
            bindToBaseCall(groupType, this, "expand")();

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.Expand(this._worksheet.getName(), this._isRowGroup, level, expand);
            }
        });

        subclass(groupType, "expandGroup", function (groupInfo, expand) {
            bindToBaseCall(groupType, this, "expandGroup")(groupInfo, expand);

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.ExpandGroup(this._worksheet.getName(), this._isRowGroup, groupInfo.start, groupInfo.end, groupInfo.level, expand);
            }
        });

        subclass(groupType, "setCollapsed", function (index, collapsed) {
            bindToBaseCall(groupType, this, "setCollapsed")(index, collapsed);

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.SetCollapsed(this._worksheet.getName(), this._isRowGroup, index, collapsed);
            }
        });

        subclass(groupType, "setDirection", function (direction) {
            bindToBaseCall(groupType, this, "setDirection")(direction);

            if (this._worksheet && this._worksheet.parent && this._worksheet.parent.spreadsheetObject) {
                var t = this._worksheet.parent.spreadsheetObject;
                t.SetRangeGroupDirection(this._worksheet.getName(), this._isRowGroup, direction);
            }
        });
    })(GrapeCity.UI.RangeGroup);
    //</editor-fold>

    //<editor-fold desc="RowFilter">
    (function (filterBase) {
        subclass(filterBase, "addFilterItem", function (col, filterItem) {
            bindToBaseCall(filterBase, this, "addFilterItem")(col, filterItem);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.AddFilterItem(this.sheet.getName(), col , filterItem);
            }
        });
        subclass(filterBase, "filter", function (col) {
            bindToBaseCall(filterBase, this, "filter")(col);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.Filter(this.sheet.getName(), col);
            }
        });
        subclass(filterBase, "unfilter", function (col) {
            bindToBaseCall(filterBase, this, "unfilter")(col);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.UnFilter(this.sheet.getName(), col);
            }
        });
        subclass(filterBase, "reFilter", function () {
            bindToBaseCall(filterBase, this, "reFilter")();

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                var name = this.sheet.getName();
                t.ReFilter(name);
                t.InvalidateSheet(name);
            }
        });
        subclass(filterBase, "removeFilterItems", function (col) {
            bindToBaseCall(filterBase, this, "removeFilterItems")(col);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.RemoveFilterItems(this.sheet.getName(), col);
            }
        });
        subclass(filterBase, "reset", function () {
            bindToBaseCall(filterBase, this, "reset")();

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                var name = this.sheet.getName();
                t.UnFilter(name);
                t.ResetFilter(name);
                t.InvalidateSheet(name);
            }
        });
        subclass(filterBase, "sortColumn", function (col, ascending) {
            bindToBaseCall(filterBase, this, "sortColumn")(col, ascending);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.SortColumn(this.sheet.getName(), col, ascending, (this.sheet.rowFilter()) ? this.sheet.rowFilter().range : null);
            }
        });
        subclass(filterBase, "getSortState", function (col) {
            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                return t.GetSortState(this.sheet.getName(), col);
            } else {
                return bindToBaseCall(filterBase, this, "getSortState")(col);
            }
        });
        subclass(filterBase, "setShowFilterButton", function (value) {
            bindToBaseCall(filterBase, this, "setShowFilterButton")(value);

            if (this.sheet && this.sheet.parent && this.sheet.parent.spreadsheetObject) {
                var t = this.sheet.parent.spreadsheetObject;
                t.SetShowFilterButton(this.sheet.getName(), value);
            }
        });
    })(GrapeCity.UI.RowFilterBase);
    //</editor-fold>

    //<editor-fold desc="CellValueRule">
    (function (cellValueRuleType) {
        // override cellValueRule
        cellValueRuleType.prototype.ruleType = GrapeCity.UI.RuleType.CellValueRule;

    })(GrapeCity.UI.CellValueRule);
    //</editor-fold>

    //<editor-fold desc="SpecificTextRule">
    (function (specificTextRuleType) {
        // override specificTextRule
        specificTextRuleType.prototype.ruleType = GrapeCity.UI.RuleType.SpecificTextRule;

    })(GrapeCity.UI.SpecificTextRule);
    //</editor-fold>

    //<editor-fold desc="FormulaRule">
    (function (formulaRuleType) {
        // override formulaRule
        formulaRuleType.prototype.ruleType = GrapeCity.UI.RuleType.FormulaRule;

    })(GrapeCity.UI.FormulaRule);
    //</editor-fold>

    //<editor-fold desc="DateOccurringRule">
    (function (dateOccurringRuleType) {
        // override dateOccurringRule
        dateOccurringRuleType.prototype.ruleType = GrapeCity.UI.RuleType.DateOccurringRule;

    })(GrapeCity.UI.DateOccurringRule);
    //</editor-fold>

    //<editor-fold desc="Top10Rule">
    (function (top10RuleType) {
        // override top10Rule
        top10RuleType.prototype.ruleType = GrapeCity.UI.RuleType.Top10Rule;

    })(GrapeCity.UI.Top10Rule);
    //</editor-fold>

    //<editor-fold desc="UniqueRule">
    (function (uniqueRuleType) {
        // override uniqueRule
        uniqueRuleType.prototype.ruleType = GrapeCity.UI.RuleType.UniqueRule;

    })(GrapeCity.UI.UniqueRule);
    //</editor-fold>

    //<editor-fold desc="DuplicateRule">
    (function (duplicateRuleType) {
        // override duplicateRule
        duplicateRuleType.prototype.ruleType = GrapeCity.UI.RuleType.DuplicateRule;

    })(GrapeCity.UI.DuplicateRule);
    //</editor-fold>

    //<editor-fold desc="AverageRule">
    (function (averageRuleType) {
        // override averageRule
        averageRuleType.prototype.ruleType = GrapeCity.UI.RuleType.AverageRule;

    })(GrapeCity.UI.AverageRule);
    //</editor-fold>

    //<editor-fold desc="TwoScaleRule">
    (function (twoScaleRuleType) {
        // override twoScaleRule
        twoScaleRuleType.prototype.ruleType = GrapeCity.UI.RuleType.TwoScaleRule;

    })(GrapeCity.UI.TwoScaleRule);
    //</editor-fold>

    //<editor-fold desc="ThreeScaleRule">
    (function (threeScaleRuleType) {
        // override threeScaleRule
        threeScaleRuleType.prototype.ruleType = GrapeCity.UI.RuleType.ThreeScaleRule;

    })(GrapeCity.UI.ThreeScaleRule);
    //</editor-fold>

    //<editor-fold desc="DataBarRule">
    (function (dataBarRuleType) {
        // override DataBarRule
        dataBarRuleType.prototype.ruleType = GrapeCity.UI.RuleType.DataBarRule;

    })(GrapeCity.UI.DataBarRule);
    //</editor-fold>

    //<editor-fold desc="IconSetRule">
    (function (iconSetRuleType) {
        // override IconSetRule
        iconSetRuleType.prototype.ruleType = GrapeCity.UI.RuleType.IconSetRule;

    })(GrapeCity.UI.IconSetRule);
    //</editor-fold>

    //<editor-fold desc="ConditionalFormats">
    (function (cfType) {
        // override ConditionalFormats
        subclass(cfType, "addRule", function (rule) {
            rule = bindToBaseCall(cfType, this, "addRule")(rule);

            // do custom action
            if (this.worksheet && this.worksheet.parent && this.worksheet.parent.spreadsheetObject) {
                var t = this.worksheet.parent.spreadsheetObject;
                var ruleType = rule.ruleType;
                if (ruleType === GrapeCity.UI.RuleType.TwoScaleRule) {
                    rule.minType = rule.getMinimumType();
                    rule.minValue = rule.getMinimumValue();
                    rule.minColor = rule.getMinimumColor();

                    rule.maxType = rule.getMaximumType();
                    rule.maxValue = rule.getMaximumValue();
                    rule.maxColor = rule.getMaximumColor();
                } else if (ruleType === GrapeCity.UI.RuleType.ThreeScaleRule) {
                    rule.minType = rule.getMinimumType();
                    rule.minValue = rule.getMinimumValue();
                    rule.minColor = rule.getMinimumColor();

                    rule.midType = rule.getMidpointType();
                    rule.midValue = rule.getMidpointValue();
                    rule.midColor = rule.getMidpointColor();

                    rule.maxType = rule.getMaximumType();
                    rule.maxValue = rule.getMaximumValue();
                    rule.maxColor = rule.getMaximumColor();
                } else if (ruleType === GrapeCity.UI.RuleType.DataBarRule) {
                    rule._minType = rule.minimumType();
                    rule._minValue = rule.minimumValue();
                    rule._maxType = rule.maximumType();
                    rule._maxValue = rule.maximumValue();
                }
                t.AddRule(this.worksheet.getName(), rule);
            }

            return rule;
        });

        subclass(cfType, "removeRule", function (rule) {
            // do custom action
            if (this.worksheet && this.worksheet.parent && this.worksheet.parent.spreadsheetObject) {
                var t = this.worksheet.parent.spreadsheetObject;
                if (rule && this.rules) {
                    for (var i = 0; i < this.rules.length; i++) {
                        if (this.rules[i] === rule) {
                            t.RemoveRule(this.worksheet.getName(), i);
                            break;
                        }
                    }
                }
            }

            bindToBaseCall(cfType, this, "removeRule")(rule);

        });

        subclass(cfType, "removeRuleByRange", function (row, column, rowCount, columnCount) {
            // do custom action
            if (this.worksheet && this.worksheet.parent && this.worksheet.parent.spreadsheetObject) {
                var t = this.worksheet.parent.spreadsheetObject;
                t.RemoveRule(this.worksheet.getName(), row, column, rowCount, columnCount);
            }

            bindToBaseCall(cfType, this, "removeRuleByRange")(row, column, rowCount, columnCount);
        });

        subclass(cfType, "clearRule", function () {
            // do custom action
            if (this.worksheet && this.worksheet.parent && this.worksheet.parent.spreadsheetObject) {
                var t = this.worksheet.parent.spreadsheetObject;
                t.ClearRule(this.worksheet.getName());
            }

            bindToBaseCall(cfType, this, "clearRule")();
        });

    })(GrapeCity.UI.ConditionalFormats);
    //</editor-fold>

    //<editor-fold desc="DefaultDataValidator">
    (function (dvType) {
        // override DefaultDataValidator
        overrideClassMethod(dvType, "createNumberValidator", function (typeOperator, v1, v2, isIntegerValue) {
            var dv = dvType._o_createNumberValidator.call(this, typeOperator, v1, v2, isIntegerValue);
            if (dv) {
                dv._value1 = convertToSXValue(v1);
                dv._value2 = convertToSXValue(v2);
            }
            return dv;
        });

        overrideClassMethod(dvType, "createDateValidator", function (typeOperator, v1, v2) {
            var dv = dvType._o_createDateValidator.call(this, typeOperator, v1, v2);
            if (dv) {
                dv._value1 = convertToSXValue(v1);
                dv._value2 = convertToSXValue(v2);
            }
            return dv;
        });

        overrideClassMethod(dvType, "createTextLengthValidator", function (typeOperator, v1, v2) {
            var dv = dvType._o_createTextLengthValidator.call(this, typeOperator, v1, v2);
            if (dv) {
                dv._value1 = convertToSXValue(v1);
                dv._value2 = convertToSXValue(v2);
            }
            return dv;
        });

        overrideClassMethod(dvType, "createFormulaValidator", function (formula) {
            var dv = dvType._o_createFormulaValidator.call(this, formula);
            if (dv) {
                dv._value1 = convertToSXValue(formula);
            }
            return dv;
        });

        overrideClassMethod(dvType, "createFormulaListValidator", function (formula) {
            var dv = dvType._o_createFormulaListValidator.call(this, formula);
            if (dv) {
                dv._value1 = convertToSXValue(formula);
                dv._isFormulaList = true;
            }
            return dv;
        });

        overrideClassMethod(dvType, "createListValidator", function (source) {
            var dv = dvType._o_createListValidator.call(this, source);
            if (dv) {
                dv._value1 = convertToSXValue(source);
                dv._isFormulaList = false;
            }
            return dv;
        });

        subclass(dvType, "toJSON", function () {
            var json = bindToBaseCall(dvType, this, "toJSON")();
            json._value1 = this._value1;
            json._value2 = this._value2;
            json._isFormulaList = !!this._isFormulaList;

            return json;
        });

        subclass(dvType, "fromJSON", function (settings) {
            bindToBaseCall(dvType, this, "fromJSON")(settings);

            this._value1 = settings._value1;
            this._value2 = settings._value2;
            this._isFormulaList = settings._isFormulaList;
        });
    })(GrapeCity.UI.DefaultDataValidator);
    //</editor-fold>

    //<editor-fold desc="_UndoManager">
    (function (undoManagerType) {
        subclass(undoManagerType, "canUndo", function () {
            var t = this.context().spreadsheetObject;
            if (!t && this.context().parent && this.context().parent.spreadsheetObject) {
                t = this.context().parent.spreadsheetObject;
            }

            if (t) {
                return t.GetUndoManagerCanUndo();
            }
            return bindToBaseCall(undoManagerType, this, "canUndo")();
        });

        subclass(undoManagerType, "canRedo", function () {
            var t = this.context().spreadsheetObject;
            if (!t && this.context().parent && this.context().parent.spreadsheetObject) {
                t = this.context().parent.spreadsheetObject;
            }

            if (t) {
                return t.GetUndoManagerCanRedo();
            }
            return bindToBaseCall(undoManagerType, this, "canRedo")();
        });

        subclass(undoManagerType, "undo", function () {
            var t = this.context().spreadsheetObject;
            if (!t && this.context().parent && this.context().parent.spreadsheetObject) {
                t = this.context().parent.spreadsheetObject;
            }

            if (t) {
                t.UndoMangerUndo();
            } else {
                bindToBaseCall(undoManagerType, this, "undo")();
            }
        });

        subclass(undoManagerType, "redo", function () {
            var t = this.context().spreadsheetObject;
            if (!t && this.context().parent && this.context().parent.spreadsheetObject) {
                t = this.context().parent.spreadsheetObject;
            }

            if (t) {
                t.UndoMangerRedo();
            } else {
                bindToBaseCall(undoManagerType, this, "redo")();
            }
        });
    })(GrapeCity.UI._UndoManager);
    //</editor-fold>

    //<editor-fold desc="SpreadActions">
    (function (spreadActionsType) {
        // override SpreadActions
        spreadActionsType.navigationLeft._name = "navigationLeft";
        spreadActionsType.navigationRight._name = "navigationRight";
        spreadActionsType.navigationUp._name = "navigationUp";
        spreadActionsType.navigationDown._name = "navigationDown";
        spreadActionsType.commitInputNavigationDown._name = "commitInputNavigationDown";
        spreadActionsType.commitInputNavigationUp._name = "commitInputNavigationUp";
        spreadActionsType.navigationHome._name = "navigationHome";
        spreadActionsType.navigationHome2._name = "navigationHome2";
        spreadActionsType.navigationEnd._name = "navigationEnd";
        spreadActionsType.navigationTop._name = "navigationTop";
        spreadActionsType.navigationBottom._name = "navigationBottom";
        spreadActionsType.navigationPageUp._name = "navigationPageUp";
        spreadActionsType.navigationPageDown._name = "navigationPageDown";
        spreadActionsType.navigationNextSheet._name = "navigationNextSheet";
        spreadActionsType.navigationPreviousSheet._name = "navigationPreviousSheet";
        spreadActionsType.navigationPrevious._name = "navigationPrevious";
        spreadActionsType.navigationNext._name = "navigationNext";
        spreadActionsType.navigationFirst._name = "navigationFirst";
        spreadActionsType.navigationLast._name = "navigationLast";
        spreadActionsType.commitInputNavigationTabNext._name = "commitInputNavigationTabNext";
        spreadActionsType.commitInputNavigationTabPrevious._name = "commitInputNavigationTabPrevious";
        spreadActionsType.cancelInput._name = "cancelInput";
        spreadActionsType.clear._name = "clear";
        spreadActionsType.clearAndEditing._name = "clearAndEditing";
        spreadActionsType.copy._name = "copy";
        spreadActionsType.cut._name = "cut";
        spreadActionsType.paste._name = "paste";
        spreadActionsType.selectionLeft._name = "selectionLeft";
        spreadActionsType.selectionRight._name = "selectionRight";
        spreadActionsType.selectionUp._name = "selectionUp";
        spreadActionsType.selectionDown._name = "selectionDown";
        spreadActionsType.selectionHome._name = "selectionHome";
        spreadActionsType.selectionEnd._name = "selectionEnd";
        spreadActionsType.selectionPageUp._name = "selectionPageUp";
        spreadActionsType.selectionPageDown._name = "selectionPageDown";
        spreadActionsType.selectionTop._name = "selectionTop";
        spreadActionsType.selectionBottom._name = "selectionBottom";
        spreadActionsType.selectionFirst._name = "selectionFirst";
        spreadActionsType.selectionLast._name = "selectionLast";
        spreadActionsType.undo._name = "undo";
        spreadActionsType.redo._name = "redo";
    })(GrapeCity.UI.SpreadActions);
    //</editor-fold>

    //<editor-fold desc="RelationCondition">
    (function (relationConditionType) {
        relationConditionType.prototype.conType = GrapeCity.UI.ConditionType.RelationCondition;

    })(GrapeCity.UI.RelationCondition);
    //</editor-fold>

    //<editor-fold desc="NumberCondition">
    (function (numberConditionType) {
        numberConditionType.prototype.conType = GrapeCity.UI.ConditionType.NumberCondition;

    })(GrapeCity.UI.NumberCondition);
    //</editor-fold>

    //<editor-fold desc="TextCondition">
    (function (textConditionType) {
        textConditionType.prototype.conType = GrapeCity.UI.ConditionType.TextCondition;

    })(GrapeCity.UI.TextCondition);
    //</editor-fold>

    //<editor-fold desc="ColorCondition">
    (function (colorConditionType) {
        colorConditionType.prototype.conType = GrapeCity.UI.ConditionType.ColorCondition;

    })(GrapeCity.UI.ColorCondition);
    //</editor-fold>

    //<editor-fold desc="FormulaCondition">
    (function (formulaConditionType) {
        formulaConditionType.prototype.conType = GrapeCity.UI.ConditionType.FormulaCondition;

    })(GrapeCity.UI.FormulaCondition);
    //</editor-fold>

    //<editor-fold desc="DateCondition">
    (function (dateConditionType) {
        dateConditionType.prototype.conType = GrapeCity.UI.ConditionType.DateCondition;

    })(GrapeCity.UI.DateCondition);
    //</editor-fold>

    //<editor-fold desc="DateExCondition">
    (function (dateExConditionType) {
        dateExConditionType.prototype.conType = GrapeCity.UI.ConditionType.DateExCondition;

    })(GrapeCity.UI.DateExCondition);
    //</editor-fold>

    //<editor-fold desc="TextLengthCondition">
    (function (textLengthConditionType) {
        textLengthConditionType.prototype.conType = GrapeCity.UI.ConditionType.TextLengthCondition;

    })(GrapeCity.UI.TextLengthCondition);
    //</editor-fold>

    //<editor-fold desc="Top10Condition">
    (function (top10ConditionType) {
        top10ConditionType.prototype.conType = GrapeCity.UI.ConditionType.Top10Condition;

    })(GrapeCity.UI.Top10Condition);
    //</editor-fold>

    //<editor-fold desc="UniqueCondition">
    (function (uniqueConditionType) {
        uniqueConditionType.prototype.conType = GrapeCity.UI.ConditionType.UniqueCondition;

    })(GrapeCity.UI.UniqueCondition);
    //</editor-fold>

    //<editor-fold desc="AverageCondition">
    (function (averageConditionType) {
        averageConditionType.prototype.conType = GrapeCity.UI.ConditionType.AverageCondition;

    })(GrapeCity.UI.AverageCondition);
    //</editor-fold>

    //<editor-fold desc="CellValueCondition">
    (function (cellValueConditionType) {
        cellValueConditionType.prototype.conType = GrapeCity.UI.ConditionType.CellValueCondition;

    })(GrapeCity.UI.CellValueCondition);
    //</editor-fold>

    //<editor-fold desc="AreaCondition">
    (function (areaConditionType) {
        areaConditionType.prototype.conType = GrapeCity.UI.ConditionType.AreaCondition;

    })(GrapeCity.UI.AreaCondition);
    //</editor-fold>
})();