1 /** 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 **/ 6 7 // Checking for "chrome" availability allows this app code to be tested in 8 // non-Chrome browsers, which is useful for example to test touch support with 9 // a non-Chrome touch device. 10 // Checking for "chrome.shell" allows testing under app_shell, which does not 11 // have chrome.app APIs. 12 // Checking for "chrome.app.runtime" availability allows testing in a regular 13 // web page (like tests/manual.html). 14 if (typeof chrome !== 'undefined' && chrome.app && chrome.app.runtime) { 15 var showCalculatorWindow = function () { 16 chrome.app.window.create('calculator.html', { 17 innerBounds: { 18 width: 243, minWidth: 243, maxWidth: 243, 19 height: 380, minHeight: 380, maxHeight: 380 20 }, 21 id: 'calculator' 22 }, function(appWindow) { 23 appWindow.contentWindow.onload = function() { 24 new Controller(new Model(9), new View(appWindow.contentWindow)); 25 }; 26 }); 27 } 28 29 chrome.app.runtime.onLaunched.addListener(showCalculatorWindow); 30 } 31 32 function Controller(model, view) { 33 this.inputs = this.defineInputs_(); 34 this.model = model; 35 this.view = view; 36 this.view.onButton = function(button) { 37 this.handleInput_(this.inputs.byButton[button]); 38 }.bind(this); 39 this.view.onKey = function(key) { 40 this.handleInput_(this.inputs.byKey[key]); 41 }.bind(this); 42 } 43 44 /** @private */ 45 Controller.prototype.defineInputs_ = function() { 46 var inputs = {byButton: {}, byKey: {}}; 47 inputs.byButton['zero'] = inputs.byKey['48'] = inputs.byKey['96'] = '0'; 48 inputs.byButton['one'] = inputs.byKey['49'] = inputs.byKey['97'] = '1'; 49 inputs.byButton['two'] = inputs.byKey['50'] = inputs.byKey['98'] = '2'; 50 inputs.byButton['three'] = inputs.byKey['51'] = inputs.byKey['99'] = '3'; 51 inputs.byButton['four'] = inputs.byKey['52'] = inputs.byKey['100'] = '4'; 52 inputs.byButton['five'] = inputs.byKey['53'] = inputs.byKey['101'] = '5'; 53 inputs.byButton['six'] = inputs.byKey['54'] = inputs.byKey['102'] = '6'; 54 inputs.byButton['seven'] = inputs.byKey['55'] = inputs.byKey['103'] = '7'; 55 inputs.byButton['eight'] = inputs.byKey['56'] = inputs.byKey['104'] = '8'; 56 inputs.byButton['nine'] = inputs.byKey['57'] = inputs.byKey['105'] = '9'; 57 inputs.byButton['point'] = inputs.byKey['190'] = inputs.byKey['110'] = '.'; 58 inputs.byButton['add'] = inputs.byKey['^187'] = inputs.byKey['107'] = '+'; 59 inputs.byButton['subtract'] = inputs.byKey['189'] = inputs.byKey['109'] = '-'; 60 inputs.byButton['multiply'] = inputs.byKey['^56'] = inputs.byKey['106'] = '*'; 61 inputs.byButton['divide'] = inputs.byKey['191'] = inputs.byKey['111'] = '/'; 62 inputs.byButton['equals'] = inputs.byKey['187'] = inputs.byKey['13'] = '='; 63 inputs.byButton['negate'] = inputs.byKey['32'] = '+ / -'; 64 inputs.byButton['clear'] = inputs.byKey['67'] = 'AC'; 65 inputs.byButton['back'] = inputs.byKey['8'] = 'back'; 66 return inputs; 67 }; 68 69 /** @private */ 70 Controller.prototype.handleInput_ = function(input) { 71 var values, accumulator, operator, operand; 72 if (input) { 73 values = this.model.handle(input); 74 accumulator = values.accumulator; 75 operator = values.operator; 76 operand = values.operand; 77 if (input === 'AC') { 78 this.view.clearDisplay({operand: '0'}); 79 } else if (input === '=') { 80 this.view.addResults({accumulator: accumulator, operand: accumulator}); 81 } else if (input.match(/^[+*/-]$/)) { 82 this.updateValues_({accumulator: accumulator}); 83 this.view.addValues({operator: values.operator}); 84 } else if (!this.updateValues_({operator: operator, operand: operand})) { 85 this.view.addValues({operator: operator, operand: operand}); 86 } 87 } 88 }; 89 90 /** @private */ 91 Controller.prototype.updateValues_ = function(values) { 92 // Values which are "finalized" (which have an accumulator value) shouldn't 93 // and won't be updated, and this method will return false for them. 94 var before = this.view.getValues(); 95 var after = !before.accumulator ? values : {}; 96 this.view.setValues({ 97 accumulator: this.getUpdatedValue_(before, after, 'accumulator'), 98 operator: this.getUpdatedValue_(before, after, 'operator'), 99 operand: this.getUpdatedValue_(before, after, 'operand', !before.operator) 100 }); 101 return !before.accumulator; 102 } 103 104 /** @private */ 105 Controller.prototype.getUpdatedValue_ = function(before, after, key, zero) { 106 var value = (typeof after[key] !== 'undefined') ? after[key] : before[key]; 107 return zero ? (value || '0') : value; 108 } 109