function Calculator() {

    this.init();

    this.cfg = {
        hasProfile: false,
        title: "",
        hasSettingsBtn: false,
        hasRefreshBtn: false,
        module: "Calculator"
    }


    this.numpadButtons = [
        [ {type: "sys1", numkey: "sys", action: "memoryClear()", text: "MC"},
          {type: "sys1", numkey: "sys", action: "memoryRestore()", text: "MR"},
          {type: "sys1", numkey: "sys", action: "memoryStore()", text: "MS"},
          {type: "sys1", numkey: "sys", action: "memoryAdd()", text: "M+"},
          {type: "sys2", numkey: "sys", action: "clear()", text: "C"},
          {type: "sys2", numkey: "sys", action: "clearE()", text: "CE"} ],

        [ {type: "std", numkey: "num", action: "addNumber(7)", text: "7"},
          {type: "std", numkey: "num", action: "addNumber(8)", text: "8"},
          {type: "std", numkey: "num", action: "addNumber(9)", text: "9"},
          {type: "std", numkey: "op", action: "setOperation('/')", text: "/"},
          {type: "std", numkey: "op", action: "evalSqrt()", text: "sqrt"} ],

        [ {type: "std", numkey: "num", action: "addNumber(4)", text: "4"},
          {type: "std", numkey: "num", action: "addNumber(5)", text: "5"},
          {type: "std", numkey: "num", action: "addNumber(6)", text: "6"},
          {type: "std", numkey: "op", action: "setOperation('*')", text: "*"},
          {type: "std", numkey: "op", action: "evalPercent()", text: "%"} ],

        [ {type: "std", numkey: "num", action: "addNumber(1)", text: "1"},
          {type: "std", numkey: "num", action: "addNumber(2)", text: "2"},
          {type: "std", numkey: "num", action: "addNumber(3)", text: "3"},
          {type: "std", numkey: "op", action: "setOperation('-')", text: "-"},
          {type: "std", numkey: "op", action: "eval1x()", text: "1/x"} ],

        [ {type: "std", numkey: "op", action: "changeSign()", text: "+/-"},
          {type: "std", numkey: "num", action: "addNumber(0)", text: "0"},
          {type: "std", numkey: "num", action: "addPoint()", text: ","},
          {type: "std", numkey: "op", action: "setOperation('+')", text: "+"},
          {type: "std", numkey: "op", action: "evalute()", text: "="} ]
    ]



    this.onBuildInterface = function() {
        var numpadModel = [];
        for(var r in this.numpadButtons) {
            var rowModel = [];
            for(var b in this.numpadButtons[r]) {
                rowModel.push(
                    { tag: "div", className: "calc_btn_" + this.numpadButtons[r][b].type,
                      childs: [
                        { tag: "button", innerHTML: this.numpadButtons[r][b].text, className: "calc_padkey_"+ this.numpadButtons[r][b].numkey,
                          events: { onclick: this.numpadButtons[r][b].action }}
                      ]});
            }
            numpadModel.push(
                { tag: "div", className: "calc_numpad_row",
                  childs: rowModel });
        }


        this.buildDomModel(this.elements["content"], [
            { tag: "div", className: "calc_display", innerHTML: "0",
              id: "display"},
            { tag: "div", className: "calc_numpad",
              childs: numpadModel }
        ]);
    }



    this.onOpen = function() {
        this.setTitle(loc.text("calculator_title"));
    }




    


    this.addPointFlag = false;
    this.memory = null;
    this.operation = null;
    this.activeNumber = 0;
    this.needClear = false;
    this.isError = false;




    this.getValue = function() {
        var v = trim(this.elements["display"].innerHTML);
        if(v == "E") {
            this.setValue(0);
            v = "0";
        }
        return v;
    }


    this.setValue = function(v) {
        this.elements["display"].innerHTML = v;
    }





    this.addNumber = function(n) {
        if(this.isError) {
            this.setValue(0);
            this.isError = false;
        }

        if(this.needClear) {
            this.setValue(0);
            this.needClear = false;
        }

        if((this.getValue() == "0") && !this.addPointFlag) {
            this.setValue(n);
        } else {
            if(this.addPointFlag) {
                this.elements["display"].innerHTML += ".";
            }
            this.elements["display"].innerHTML += n;
        }
        this.addPointFlag = false;
    }


    this.addPoint = function() {
        if(this.needClear) {
            this.setValue(0);
            this.needClear = false;
        }

        if(this.getValue().indexOf(".") == -1) {
            this.addPointFlag = true;
        }
    }





    this.setOperation = function(op) {
        if(this.operation != null) {
            this.evalute();
        }
        this.addPointFlag = false;
        this.activeNumber = parseFloat(this.getValue());
        this.operation = op;
        this.needClear = true;
    }


    this.evalute = function() {
        if(this.operation != null) {
            var v = parseFloat(this.getValue());
            switch(this.operation) {
                case "*":
                    this.setValue(v * this.activeNumber);
                    break;

                case "+":
                    this.setValue(v + this.activeNumber);
                    break;

                case "-":
                    this.setValue(this.activeNumber - v);
                    break;

                case "/":
                    if(v != 0) {
                        this.setValue(this.activeNumber / v);
                    } else {
                        this.setValue("E");
                    }
                    break;
            }
            this.operation = false;
            this.addPointFlag = false;
            this.needClear = true;
        }
    }


    this.evalPercent = function() {
        if(this.activeNumber != null && this.operation != null) {
            this.addPointFlag = false;
            var v = parseFloat(this.getValue());
            this.setValue(v*this.activeNumber/100);
        }
    }


    this.evalSqrt = function() {
        this.addPointFlag = false;
        var v = parseFloat(this.getValue());
        this.setValue(Math.sqrt(v));
    }


    this.eval1x = function() {
        this.addPointFlag = false;        
        var v = parseFloat(this.getValue());
        if(v != 0) {
            this.setValue(1/v);
        } else {
            this.setValue("E");
        }
    }


    this.changeSign = function() {
        var v = parseFloat(this.getValue());
        if(v != 0) {
            this.setValue(-v);
        }
    }






    this.memoryClear = function() {
        this.memory = null;
    }

    this.memoryRestore = function() {
        if(this.memory != null) {
            this.setValue(this.memory);
            this.needClear = true;
        }
    }

    this.memoryStore = function() {
        this.memory = parseFloat(this.getValue());
    }

    this.memoryAdd = function() {
        if(this.memory == null) {
            this.memory = 0;
        }
        this.memory += parseFloat(this.getValue());
    }





    this.clear = function() {
        this.addPointFlag = false;
        this.operation = null;
        this.activeNumber = 0;
        this.setValue(0);
    }


    this.clearE = function() {
        this.addPointFlag = false;
        this.setValue(0);
    }

}
Calculator.prototype = new Widget();