Simple calculadora en Sencha Touch 2

Después de instalar Sencha CMD y el SDK de Sencha (descargar el Free Commercial Version http://docs.sencha.com/touch/2.3.0/#!/guide) necesitamos crear el projecto Sencha Touch con el siguiente comando:

sencha generate app CalcAndroid ./CalcAndroid

Luego necesitamos crear los archivos view/Calc.js (CalcAndroid.view.Calc) y el archivo controller/Calc.js (CalcAndroid.controller.Calc), una vez creados se necesita agregarlos al archivo app.js que se encargara de ponerlos a disposición de la app y especificar a la aplicación con que iniciara y que controladores están disponibles.

Ext.application({
    name: 'CalcAndroid',

    requires: [
        'Ext.MessageBox',
        'CalcAndroid.view.Calc'
    ],

    views: [
        'Calc'
    ],

    controllers: [
        'CalcAndroid.controller.Calc' // Indica que tendremos un Controlador Calc
    ],

    icon: {
        '57': 'resources/icons/Icon.png',
        '72': 'resources/icons/Icon~ipad.png',
        '114': 'resources/icons/Icon@2x.png',
        '144': 'resources/icons/Icon~ipad@2x.png'
    },

    isIconPrecomposed: true,

    startupImage: {
        '320x460': 'resources/startup/320x460.jpg',
        '640x920': 'resources/startup/640x920.png',
        '768x1004': 'resources/startup/768x1004.png',
        '748x1024': 'resources/startup/748x1024.png',
        '1536x2008': 'resources/startup/1536x2008.png',
        '1496x2048': 'resources/startup/1496x2048.png'
    },

    launch: function() {
        // Destroy the #appLoadingIndicator element
        Ext.fly('appLoadingIndicator').destroy();

        // Initialize the main view
        Ext.Viewport.add(Ext.create('CalcAndroid.view.Calc'));
    },

    onUpdated: function() {
        Ext.Msg.confirm(
            "Application Update",
            "This application has just successfully been updated to the latest version. Reload now?",
            function(buttonId) {
                if (buttonId === 'yes') {
                    window.location.reload();
                }
            }
        );
    }
});

Entonces hasta este punto tenemos el archivo view/Calc.js que tendra la vista y luego tendremos el archivo controller/Calc.js que tendra el controlador.

A continuación esta el codigo que tendria que estar en view/Calc.js que sera la vista de la calculadora.

Ext.define('CalcAndroid.view.Calc', {
    extend: 'Ext.Container',
    xtype: 'calculator',
    requires: [],
    config: {
        items: [
            {
                xtype: 'textfield',
                itemId: 'number',
                height: '8%',
                width: '90%',
                margin: '1% 5% 1% 5%'
            }, {
                xtype: 'container',
                height: '90%',
                defaults: {
                    height: '20%'
                },
                items: [
                    {
                        xtype: 'container',
                        layout: 'hbox',
                        defaults: {
                            width: '25%'
                        },
                        items: [{
                            xtype: 'button',
                            text: '7',
                            action: 'press7'
                        }, {
                            xtype: 'button',
                            text: '8',
                            action: 'press8'
                        }, {
                            xtype: 'button',
                            text: '9',
                            action: 'press9'
                        }, {
                            xtype: 'button',
                            text: '/',
                            action: 'pressDiv'
                        }]
                    }, {
                        xtype: 'container',
                        layout: 'hbox',
                        defaults: {
                            width: '25%'
                        },
                        items: [{
                            xtype: 'button',
                            text: '4',
                            action: 'press4'
                        }, {
                            xtype: 'button',
                            text: '5',
                            action: 'press5'
                        }, {
                            xtype: 'button',
                            text: '6',
                            action: 'press6'
                        }, {
                            xtype: 'button',
                            text: '*',
                            action: 'pressMul'
                        }]
                    }, {
                        xtype: 'container',
                        layout: 'hbox',
                        defaults: {
                            width: '25%'
                        },
                        items: [{
                            xtype: 'button',
                            text: '1',
                            action: 'press1'
                        }, {
                            xtype: 'button',
                            text: '2',
                            action: 'press2'
                        }, {
                            xtype: 'button',
                            text: '3',
                            action: 'press3'
                        }, {
                            xtype: 'button',
                            text: '-',
                            action: 'pressSub'
                        }]
                    }, {
                        xtype: 'container',
                        layout: 'hbox',
                        defaults: {
                            width: '25%'
                        },
                        items: [{
                            xtype: 'spacer'
                        }, {
                            xtype: 'button',
                            text: '0',
                            action: 'press0'
                        }, {
                            xtype: 'spacer'
                        }, {
                            xtype: 'button',
                            text: '+',
                            action: 'pressAdd'
                        }]
                    }, {
                        xtype: 'container',
                        layout: 'hbox',
                        defaults: {
                            width: '25%'
                        },
                        items: [{
                            xtype: 'spacer'
                        }, {
                            xtype: 'spacer'
                        }, {
                            xtype: 'spacer'
                        }, {
                            xtype: 'button',
                            text: '=',
                            action: 'pressEnter'
                        }]
                    }
                ]
            }
        ]
    }
});

A continuación esta el codigo que tendria que estar en controller/Calc.js donde estara la funcionalidad de nuestra calculadora.

Ext.define('CalcAndroid.controller.Calc', {
    extend: 'Ext.app.Controller',
    requires: [
        'CalcAndroid.view.Calc' // Necesitaremos usar la vista de 'calculator'
    ],

    config: {
        refs: {
            btn: 'button', // Referencia a todos los elementos del tipo button
            numberTextField: '#number' // Referencia al text field donde se ingresan los valores
        },
        control: {
            btn: { // Referencia a los elementos del tipo button
                tap: 'onBtnPress' // ejecuta onBtnPress cuando se presiona algun boton
            }
        }
    },

    /**
     * Este metodo se ejecuta cuando alguien preciona algun boton
     * No es la forma apropiada ya que se deberia tener una referencia a los numeros y que sea diferente que la de los operadores
     * Pero para entender el concepto se creo un solo metodo donde esta todo el funcionanmiento
     * @param btn
     */
    onBtnPress: function(btn) {
        var me = this,
            act = btn.action, // Obtiene la accion del boton presionado
            textField = me.getNumberTextField(),
            num = textField.getValue(), // Obtiene el valor actual en el text field number
            numberInt;

        for(var i=0; i<=9 ;i++) {
            if(act == 'press' + i) { // Si es un numero entonces ingresa
                if(me.last == 'op') num = ""; // si antes de este digito se presiono un operador entonces se limpia el text field
                me.last = 'num';
                if(num.length < 9) textField.setValue( num + i ); // solo añade mas digitos si tenia menos de 9
                return; // Termina el metodo por que se presiono un numero
            }
        }

        numberInt = parseInt(num);
        me.last = 'op'; // nos indica que fue lo ultimo que se presiono

        if(me.op && me.num) { // Si existia un numero y un operador anteriormente presionado entonces aplica la operacion
            if(me.op == 'div') {
                numberInt = me.num / numberInt;
            }
            if(me.op == 'mul') {
                numberInt = me.num * numberInt;
            }
            if(me.op == 'sub') {
                numberInt = me.num - numberInt;
            }
            if(me.op == 'add') {
                numberInt = me.num + numberInt;
            }
            textField.setValue("" + numberInt); // llena el text field con el resultado de la operacion
        }

        me.num = numberInt;
        if(act == 'pressDiv') {
            me.op = 'div';
        }
        else if(act == 'pressMul') {
            me.op = 'mul';
        }
        else if(act == 'pressSub') {
            me.op = 'sub';
        }
        else if(act == 'pressAdd') {
            me.op = 'add';
        }
        else { // Se presiono igual, el estado de la calculadora retorna al inicial
            me.op = null;
        }
    }
});