PageRenderTime 68ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/GraphingCalculator/GraphingCalculator/CalculatorViewController.m

https://github.com/oliverbarreto/CS193P-A4
Objective C | 376 lines | 209 code | 112 blank | 55 comment | 50 complexity | 1e64288024b27839e1df038266cf9b8a MD5 | raw file
  1. //
  2. // CalculatorViewController.m
  3. // Calculator
  4. //
  5. // Created by David Oliver Barreto Rodríguez on 08/08/11.
  6. // Copyright 2011 __MyCompanyName__. All rights reserved.
  7. //
  8. #import "CalculatorViewController.h"
  9. #pragma mark - Implementation & Synthesize Header
  10. @interface CalculatorViewController()
  11. @property (readonly) CalculatorBrain *brain; //Private & ReadOnly Model
  12. @end
  13. @implementation CalculatorViewController
  14. @synthesize brain;
  15. @synthesize display, displayMem, displayOperation, displayTypeOfAngleMetrics;
  16. @synthesize radiansModeButton;
  17. @synthesize editVariableModeEnabledButton;
  18. //@synthesize myGraphViewMVC;
  19. //-(GraphViewController *)myGraphViewMVC {
  20. // if (!myGraphViewMVC) {
  21. // myGraphViewMVC = [[GraphViewController alloc] init];
  22. // }
  23. // return myGraphViewMVC;
  24. //}
  25. #pragma mark - Utility Methods
  26. - (BOOL)isDecimalPointValid {
  27. NSString *myDisplayString = self.display.text;
  28. NSRange myRange = [myDisplayString rangeOfString:@"."];
  29. if (myRange.length == 0) return YES;
  30. else return NO;
  31. }
  32. - (void)showAlertWithTitle:(NSString *)myTitle andMessage:(NSString *)myMessage {
  33. UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:myTitle
  34. message:myMessage
  35. delegate:self
  36. cancelButtonTitle:@"OK"
  37. otherButtonTitles:nil];
  38. [myAlert autorelease];
  39. [myAlert show];
  40. self.brain.errorMessage = @"";
  41. }
  42. - (NSString *)stringForPendingOperation {
  43. if ([self.brain.waitingOperation isEqual:@"="]) {
  44. //return self.displayOperation.text = [NSString stringWithFormat:@"Op: = %g ",self.brain.waitingOperand];
  45. return self.displayOperation.text = [NSString stringWithFormat:@"Op: = %g ",self.brain.waitingOperand];
  46. } else {
  47. return self.displayOperation.text = [NSString stringWithFormat:@"Op: %g %@ ",self.brain.waitingOperand, self.brain.waitingOperation];
  48. //return self.displayOperation.text = [NSString stringWithFormat:@"Op: %g %@ ",self.brain.waitingOperand, self.brain.waitingOperation];
  49. }
  50. }
  51. - (void)updateOptionsDisplays:(UIButton *)mySender {
  52. //Creates the right setup for Displaying content on all displays on screen
  53. NSString *myOperationDisplayMSG = @"Op: ";
  54. NSString static *myTypeOfAngleMetricsMSG = @"Deg";
  55. //If there is an error when performing an operation, nothing is updaed
  56. if (![self.brain.errorMessage isEqual:@""]) {
  57. myOperationDisplayMSG = self.brain.errorMessage;
  58. //[self showAlertWithTitle:@"Invalid Operation" andMessage:self.brain.errorMessage];
  59. self.brain.errorMessage = @"";
  60. } else {
  61. //Checks state of typeOfAngleMetrics Rdn vs Deg and displays correct info on screen
  62. if ([mySender.titleLabel.text isEqual:@"Deg"] || [mySender.titleLabel.text isEqual:@"Rdn"]) {
  63. //Change image & text of Deg/Rdn Button & Display Text;
  64. if (self.brain.radiansMode) { //Set state to work in Degrees, Show Button to show Radians text
  65. myTypeOfAngleMetricsMSG = [NSString stringWithFormat:@"Deg"];
  66. self.brain.radiansMode = NO;
  67. [radiansModeButton setTitle:@"Rdn" forState:UIControlStateNormal];
  68. //UIImage *myButtonImage = [UIImage imageNamed:@"Button_GreyLight_40.png"];
  69. [radiansModeButton setBackgroundImage:nil forState:UIControlStateNormal];
  70. } else { //Set state to work in Radians, Show Button to show Degrees text
  71. myTypeOfAngleMetricsMSG = [NSString stringWithFormat:@"Rdn"];
  72. self.brain.radiansMode = YES;
  73. [radiansModeButton setTitle:@"Deg" forState:UIControlStateNormal];
  74. UIImage *myButtonImage = [UIImage imageNamed:@"Button_GreyDark_40.png"];
  75. [radiansModeButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
  76. }
  77. }
  78. if ([mySender.titleLabel.text isEqual:@"C"]) {
  79. myOperationDisplayMSG = @"Op: ";
  80. } else {
  81. if (self.brain.waitingOperand) {
  82. myOperationDisplayMSG = [self stringForPendingOperation];
  83. } else {
  84. myOperationDisplayMSG = [NSString stringWithFormat:@"Op: "];
  85. }
  86. }
  87. }
  88. //Dsisplays updated content for all the Diplays
  89. self.displayMem.text = [NSString stringWithFormat:@"Mem: %g", self.brain.myMem];
  90. self.displayTypeOfAngleMetrics.text = myTypeOfAngleMetricsMSG;
  91. self.displayOperation.text = myOperationDisplayMSG;
  92. }
  93. #pragma mark - IBAction Methods
  94. - (IBAction)digitPressed:(UIButton *)sender {
  95. //Performs actions when a Digit (number) is pressed
  96. NSString *digit = sender.titleLabel.text;
  97. if (userIsInTheMiddleOfTypingANumber) {
  98. if ([digit isEqual:@"."]) {
  99. if ([self isDecimalPointValid]) {
  100. self.display.text = [self.display.text stringByAppendingString:digit];
  101. }
  102. } else {
  103. self.display.text = [self.display.text stringByAppendingString:digit];
  104. }
  105. } else {
  106. self.display.text = digit;
  107. userIsInTheMiddleOfTypingANumber = YES;
  108. }
  109. }
  110. - (IBAction)operationPressed:(UIButton *)sender {
  111. //Checks if the user is in the middle of typing some number or its an final result from an operations or equals is pressed
  112. if (userIsInTheMiddleOfTypingANumber) {
  113. self.brain.operand = [self.display.text doubleValue];
  114. userIsInTheMiddleOfTypingANumber = NO;
  115. }
  116. //Evaluate before displaying
  117. double result = [self.brain performOperation:sender.titleLabel.text];
  118. if ([CalculatorBrain variablesInExpression:self.brain.expression]) {
  119. display.text = [CalculatorBrain descriptionOfExpression:brain.expression];
  120. self.displayOperation.text = @"Op: ";
  121. } else {
  122. display.text = [NSString stringWithFormat:@"%g", result];
  123. }
  124. //Update Displays in UI
  125. [self updateOptionsDisplays:sender];
  126. }
  127. - (IBAction)solvePressed:(id)sender {
  128. //If user is in the middle of typing a number when he press solve, set operand
  129. if (userIsInTheMiddleOfTypingANumber) {
  130. [self.brain setOperand:[display.text doubleValue]];
  131. userIsInTheMiddleOfTypingANumber = NO;
  132. }
  133. //If not = present at the end of internalExpression
  134. if (![[CalculatorBrain descriptionOfExpression:self.brain.expression] hasSuffix:@"= "]) {
  135. [self.brain performOperation: @"="];
  136. }
  137. //Call evaluateExpression:UssingVariablesValues:
  138. double myResult = [CalculatorBrain evaluateExpression:self.brain.expression
  139. usingVariableValues:self.brain.myVariables];
  140. //Displays updated content for all the Diplays
  141. self.display.text = [NSString stringWithFormat:@"%@ %g", [CalculatorBrain descriptionOfExpression:self.brain.expression],myResult];
  142. self.displayOperation.text = @"Op: ";
  143. [self.brain performOperation:@"C"]; //clears everything for next operation
  144. }
  145. - (IBAction)graphPressed:(id)sender {
  146. //If user is in the middle of typing a number when he press solve, set operand
  147. if (userIsInTheMiddleOfTypingANumber) {
  148. [self.brain setOperand:[display.text doubleValue]];
  149. userIsInTheMiddleOfTypingANumber = NO;
  150. }
  151. //If not = present at the end of internalExpression
  152. if (![[CalculatorBrain descriptionOfExpression:self.brain.expression] hasSuffix:@"= "]) {
  153. [self.brain performOperation: @"="];
  154. }
  155. //Graph the expression (set initial zoom, evaluate the expression for all X axis values, draw points in graph, update graph view)
  156. GraphViewController *myGraphViewMVC = [[GraphViewController alloc] init];
  157. myGraphViewMVC.myExpression = self.brain.expression;
  158. myGraphViewMVC.title = [NSString stringWithFormat:@"%@ y", [CalculatorBrain descriptionOfExpression:self.brain.expression]];
  159. [self.navigationController pushViewController:myGraphViewMVC animated:YES];
  160. //[myGraphViewMVC release]; //In Dealloc because its a property
  161. }
  162. - (IBAction)variablePressed:(UIButton *)sender{
  163. NSString *myVariablePressed = sender.titleLabel.text;
  164. if ([myVariablePressed isEqual:@"Fn"]) {
  165. //-- EXTRA CREDIT --
  166. //-- If Fn is Pressed, set/edit the Variable value in Array
  167. //Checks state of editVariableModeEnabled and displays correct info on screen
  168. //Change image of Fn Button to look like pressed;
  169. if (editVariableModeEnabled) { //Editing Variables Mode Pressed
  170. editVariableModeEnabled = NO;
  171. //UIImage *myButtonImage = [UIImage imageNamed:@"Button_GreyLight_40.png"];
  172. [editVariableModeEnabledButton setBackgroundImage:nil forState:UIControlStateNormal];
  173. } else { //Editing Variables Mode NOT Pressed
  174. editVariableModeEnabled = YES;
  175. UIImage *myButtonImage = [UIImage imageNamed:@"Button_GreyDark_40.png"];
  176. [editVariableModeEnabledButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
  177. }
  178. } else if ([myVariablePressed isEqual:@"Vars"]) {
  179. //Test Button for testing Error Conditions of the Model calling AlertView
  180. //Just for testing purposes of NSAlertView
  181. [self showAlertWithTitle:@"Current Values of Variables" andMessage:[self.brain descriptionOfMyVariables]];
  182. } else if ([myVariablePressed isEqual:@"Exp"]) {
  183. //Shows an AlertView Message with the current expression
  184. [self showAlertWithTitle:@"Current Expression" andMessage:[CalculatorBrain descriptionOfExpression:self.brain.expression]];
  185. } else { //If there is an Variable in expression, displays expression
  186. if (!editVariableModeEnabled) {
  187. //if user is typing a number (not zero),multiply the number times the variable, 8x = 8 * X
  188. if ((userIsInTheMiddleOfTypingANumber) && (![self.display.text isEqual:@"0"])) {
  189. [self.brain setOperand:[self.display.text doubleValue]];
  190. [self.brain performOperation:@"*"];
  191. }
  192. userIsInTheMiddleOfTypingANumber = NO;
  193. if ([myVariablePressed isEqual:@"x"]) { //Call SetVariableAsOperand:
  194. [self.brain setVariableAsOperand:@"x"];
  195. self.displayOperation.text = @"Op: ";
  196. } else if ([myVariablePressed isEqual:@"a"]) { //Call SetVariableAsOperand:
  197. [self.brain setVariableAsOperand:@"a"];
  198. self.displayOperation.text = @"Op: ";
  199. } else if ([myVariablePressed isEqual:@"b"]) { //Call SetVariableAsOperand:
  200. [self.brain setVariableAsOperand:@"b"];
  201. self.displayOperation.text = @"Op: ";
  202. }
  203. if ([CalculatorBrain variablesInExpression:self.brain.expression]) {
  204. self.display.text = [CalculatorBrain descriptionOfExpression:self.brain.expression];
  205. self.displayOperation.text = @"Op: ";
  206. } else {
  207. //TODO - Pendiente de revisar si sigue funcionando TODO igual
  208. self.displayOperation.text = @"No Variables in Expression";
  209. }
  210. } else {
  211. //Set variable value, if there is a number on screen (zero is not allowed)
  212. if ((userIsInTheMiddleOfTypingANumber) && (![self.display.text isEqual:@"0"])) {
  213. NSMutableDictionary *myMutableVariables = [[NSMutableDictionary alloc] initWithDictionary:self.brain.myVariables copyItems:YES];
  214. if ([myMutableVariables objectForKey:myVariablePressed]) {
  215. [myMutableVariables setObject:[NSNumber numberWithDouble:[self.display.text doubleValue]] forKey:myVariablePressed];
  216. }
  217. self.brain.myVariables = [myMutableVariables autorelease];
  218. //[myMutableVariables autorelease];
  219. myMutableVariables = nil;
  220. }
  221. userIsInTheMiddleOfTypingANumber = NO;
  222. }
  223. }
  224. }
  225. #pragma mark - View Lifecycle & Memory Management
  226. - (void)didReceiveMemoryWarning {
  227. // Releases the view if it doesn't have a superview.
  228. [super didReceiveMemoryWarning];
  229. // Release any cached data, images, etc that aren't in use.
  230. }
  231. // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
  232. - (void)viewDidLoad
  233. {
  234. [super viewDidLoad];
  235. brain = [[CalculatorBrain alloc] init];
  236. self.title = @"Graphing Calculator"; //Main UINavigationController Title
  237. }
  238. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  239. {
  240. // Return YES for supported orientations
  241. return (interfaceOrientation == UIInterfaceOrientationPortrait);
  242. }
  243. -(void)releaseNilsOfOutlets { //Utility methods for cleaning up memory when finished
  244. self.display = nil;
  245. self.displayMem = nil;
  246. self.displayOperation = nil;
  247. self.displayTypeOfAngleMetrics = nil;
  248. self.radiansModeButton = nil;
  249. self.editVariableModeEnabledButton = nil;
  250. }
  251. - (void)viewDidUnload {
  252. // Releasing my own created IBOutlet objects
  253. [self releaseNilsOfOutlets];
  254. [super viewDidUnload];
  255. }
  256. - (void)dealloc {
  257. // Releasing my own created IBOutlet objects
  258. [self releaseNilsOfOutlets];
  259. // Releasing my own created objects
  260. [brain release];
  261. //[myGraphViewMVC release];
  262. [super dealloc];
  263. }
  264. @end