diff --git a/lib/widgets/components/calculator/calculator-button.dart b/lib/widgets/components/calculator/calculator-button.dart new file mode 100644 index 0000000..47bbaa7 --- /dev/null +++ b/lib/widgets/components/calculator/calculator-button.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +typedef void CalculatorButtonTapCallback({String buttonText}); + +class CalculatorButton extends StatelessWidget { + CalculatorButton({this.text, @required this.onTap}); + + final String text; + final CalculatorButtonTapCallback onTap; + + @override + Widget build(BuildContext context) { + return Expanded( + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Color.fromRGBO(0, 0, 0, 0.1), + width: 0.5, + ), + ), + child: FlatButton( + onPressed: () => onTap(buttonText: text), + child: Text( + text, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500), + ), + padding: EdgeInsets.all(30), + highlightColor: Colors.blueGrey[100], + splashColor: Colors.blueAccent[100], + ))); + } +} diff --git a/lib/widgets/components/calculator/calculator-buttons.dart b/lib/widgets/components/calculator/calculator-buttons.dart new file mode 100644 index 0000000..9855d75 --- /dev/null +++ b/lib/widgets/components/calculator/calculator-buttons.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'calculator.dart'; +import 'calculator-button.dart'; +import 'calculator-row.dart'; + +class CalculatorButtons extends StatelessWidget { + CalculatorButtons({@required this.onTap}); + + final CalculatorButtonTapCallback onTap; + final calculatorButtonRows = [ + ['7', '8', '9', Calculations.DIVIDE], + ['4', '5', '6', Calculations.MULTIPLY], + ['1', '2', '3', Calculations.SUBTRACT], + [Calculations.PERIOD, '0', '00', Calculations.ADD], + [Calculations.CLEAR, Calculations.EQUAL] + ]; + + @override + Widget build(BuildContext context) { + return Column( + children: calculatorButtonRows.map((calculatorRowButtons) { + return CalculatorRow( + buttons: calculatorRowButtons, + onTap: onTap, + ); + }).toList() + ); + } +} diff --git a/lib/widgets/components/calculator/calculator-row.dart b/lib/widgets/components/calculator/calculator-row.dart new file mode 100644 index 0000000..1b535f4 --- /dev/null +++ b/lib/widgets/components/calculator/calculator-row.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'calculator-button.dart'; + +class CalculatorRow extends StatelessWidget { + CalculatorRow({@required this.buttons, @required this.onTap }); + + final List buttons; + final CalculatorButtonTapCallback onTap; + + @override + Widget build(BuildContext context) { + return Row( + children: rowButtons(), + mainAxisAlignment: MainAxisAlignment.spaceAround, + ); + } + + List rowButtons() { + List rowButtons = []; + + buttons.forEach((String buttonText) { + rowButtons.add( + CalculatorButton( + text: buttonText, + onTap: onTap, + ), + ); + }); + + return rowButtons; + } +} diff --git a/lib/widgets/components/calculator/calculator.dart b/lib/widgets/components/calculator/calculator.dart new file mode 100644 index 0000000..6bdc1f0 --- /dev/null +++ b/lib/widgets/components/calculator/calculator.dart @@ -0,0 +1,82 @@ +import 'number-formatter.dart'; + +class Calculations { + static const PERIOD = '.'; + static const MULTIPLY = '*'; + static const SUBTRACT = '-'; + static const ADD = '+'; + static const DIVIDE = '/'; + static const CLEAR = 'CLEAR'; + static const EQUAL = '='; + static const OPERATIONS = [ + Calculations.ADD, + Calculations.MULTIPLY, + Calculations.SUBTRACT, + Calculations.DIVIDE, + ]; + + static double add(double a, double b) => a + b; + static double subtract(double a, double b) => a - b; + static double divide(double a, double b) => a / b; + static double multiply(double a, double b) => a * b; +} + +class Calculator { + static String parseString(String text) { + List numbersToAdd; + double a, b, result; + if (text.contains(Calculations.ADD)) { + numbersToAdd = text.split(Calculations.ADD); + a = double.parse(numbersToAdd[0]); + b = double.parse(numbersToAdd[1]); + + result = Calculations.add(a, b); + } else if (text.contains(Calculations.MULTIPLY)) { + numbersToAdd = text.split(Calculations.MULTIPLY); + a = double.parse(numbersToAdd[0]); + b = double.parse(numbersToAdd[1]); + + result = Calculations.multiply(a, b); + } else if (text.contains(Calculations.DIVIDE)) { + numbersToAdd = text.split(Calculations.DIVIDE); + a = double.parse(numbersToAdd[0]); + b = double.parse(numbersToAdd[1]); + + result = Calculations.divide(a, b); + } else if (text.contains(Calculations.SUBTRACT)) { + numbersToAdd = text.split(Calculations.SUBTRACT); + a = double.parse(numbersToAdd[0]); + b = double.parse(numbersToAdd[1]); + + result = Calculations.subtract(a, b); + } else { + return text; + } + + return NumberFormatter.format(result.toString()); + } + + static String addPeriod(String calculatorString) { + if (calculatorString.isEmpty) { + return calculatorString = '0${Calculations.PERIOD}'; + } + + RegExp exp = new RegExp(r"\d\."); + Iterable matches = exp.allMatches(calculatorString); + int maxMatches = Calculator.includesOperation(calculatorString) ? 2 : 1; + + return matches.length == maxMatches + ? calculatorString + : calculatorString += Calculations.PERIOD; + } + + static bool includesOperation(String calculatorString) { + for (var operation in Calculations.OPERATIONS) { + if (calculatorString.contains(operation)) { + return true; + } + } + + return false; + } +} diff --git a/lib/widgets/components/calculator/number-display.dart b/lib/widgets/components/calculator/number-display.dart new file mode 100644 index 0000000..9c44a33 --- /dev/null +++ b/lib/widgets/components/calculator/number-display.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class NumberDisplay extends StatelessWidget { + NumberDisplay({this.value: ''}); + + final String value; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(20), + child: Row( + children: [ + Text( + value, + style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold), + ), + ], + mainAxisAlignment: MainAxisAlignment.end, + )); + } +} diff --git a/lib/widgets/components/calculator/number-formatter.dart b/lib/widgets/components/calculator/number-formatter.dart new file mode 100644 index 0000000..934bfd1 --- /dev/null +++ b/lib/widgets/components/calculator/number-formatter.dart @@ -0,0 +1,15 @@ +class NumberFormatter { + static String format(String text) { + try { + double parsedNumber = double.parse(text); + + if ((parsedNumber != double.infinity) && (parsedNumber == parsedNumber.floor())) { + return parsedNumber.truncate().toString(); + } + + return text; + } catch(err) { + return text; + } + } +}