diff --git a/AppSalesMobile.xcodeproj/project.pbxproj b/AppSalesMobile.xcodeproj/project.pbxproj index 2c085575..f2de31fd 100755 --- a/AppSalesMobile.xcodeproj/project.pbxproj +++ b/AppSalesMobile.xcodeproj/project.pbxproj @@ -22,6 +22,21 @@ 7F17E0570ED4F21E0005D8AF /* CurrencySelectionDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F17E0560ED4F21E0005D8AF /* CurrencySelectionDialog.m */; }; 7F29EA420ED861B20018C18A /* help in Resources */ = {isa = PBXBuildFile; fileRef = 7F29EA340ED861B20018C18A /* help */; }; 7F29EA630ED861CE0018C18A /* HelpBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F29EA620ED861CE0018C18A /* HelpBrowser.m */; }; + 7F46956A1196403700E82747 /* TB_Calculator.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695691196403700E82747 /* TB_Calculator.png */; }; + 7F4695811196436200E82747 /* MovableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F46957E1196436200E82747 /* MovableView.m */; }; + 7F4695821196436200E82747 /* CalculatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F4695801196436200E82747 /* CalculatorView.m */; }; + 7F4695941196439900E82747 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F4695931196439900E82747 /* QuartzCore.framework */; }; + 7F4695AA119643CE00E82747 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F4695A9119643CE00E82747 /* AudioToolbox.framework */; }; + 7F4695B41196448900E82747 /* CalculatorClick.caf in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695B31196448900E82747 /* CalculatorClick.caf */; }; + 7F4695C1119644B500E82747 /* CalculatorButtonNormal.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695B8119644B500E82747 /* CalculatorButtonNormal.png */; }; + 7F4695C2119644B500E82747 /* CalculatorButton2Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695B9119644B500E82747 /* CalculatorButton2Highlighted.png */; }; + 7F4695C3119644B500E82747 /* CalculatorButton2Normal.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BA119644B500E82747 /* CalculatorButton2Normal.png */; }; + 7F4695C4119644B500E82747 /* CalculatorButtonHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BB119644B500E82747 /* CalculatorButtonHighlighted.png */; }; + 7F4695C5119644B500E82747 /* CalculatorButton3Normal.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BC119644B500E82747 /* CalculatorButton3Normal.png */; }; + 7F4695C6119644B500E82747 /* CalculatorButton3Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BD119644B500E82747 /* CalculatorButton3Highlighted.png */; }; + 7F4695C7119644B500E82747 /* CalculatorButton4Normal.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BE119644B500E82747 /* CalculatorButton4Normal.png */; }; + 7F4695C8119644B500E82747 /* CalculatorButton4Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4695BF119644B500E82747 /* CalculatorButton4Highlighted.png */; }; + 7F46961A1196458A00E82747 /* CalculatorBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F4696191196458A00E82747 /* CalculatorBackground.png */; }; 7F47897810661CBD002415A2 /* Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7F47897710661CBD002415A2 /* Entitlements.plist */; }; 7F4A4FE9116A648000FA2019 /* PadRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F4A4FE8116A648000FA2019 /* PadRootViewController.m */; }; 7F4A50DC116A781D00FA2019 /* DashboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F4A50DB116A781D00FA2019 /* DashboardView.m */; }; @@ -376,6 +391,23 @@ 7F29EA340ED861B20018C18A /* help */ = {isa = PBXFileReference; lastKnownFileType = folder; path = help; sourceTree = ""; }; 7F29EA610ED861CE0018C18A /* HelpBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpBrowser.h; sourceTree = ""; }; 7F29EA620ED861CE0018C18A /* HelpBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HelpBrowser.m; sourceTree = ""; }; + 7F4695691196403700E82747 /* TB_Calculator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TB_Calculator.png; sourceTree = ""; }; + 7F46957D1196436200E82747 /* MovableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MovableView.h; sourceTree = ""; }; + 7F46957E1196436200E82747 /* MovableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MovableView.m; sourceTree = ""; }; + 7F46957F1196436200E82747 /* CalculatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CalculatorView.h; sourceTree = ""; }; + 7F4695801196436200E82747 /* CalculatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CalculatorView.m; sourceTree = ""; }; + 7F4695931196439900E82747 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 7F4695A9119643CE00E82747 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 7F4695B31196448900E82747 /* CalculatorClick.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = CalculatorClick.caf; sourceTree = ""; }; + 7F4695B8119644B500E82747 /* CalculatorButtonNormal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButtonNormal.png; path = ../CalculatorButtonNormal.png; sourceTree = ""; }; + 7F4695B9119644B500E82747 /* CalculatorButton2Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton2Highlighted.png; path = ../CalculatorButton2Highlighted.png; sourceTree = ""; }; + 7F4695BA119644B500E82747 /* CalculatorButton2Normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton2Normal.png; path = ../CalculatorButton2Normal.png; sourceTree = ""; }; + 7F4695BB119644B500E82747 /* CalculatorButtonHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButtonHighlighted.png; path = ../CalculatorButtonHighlighted.png; sourceTree = ""; }; + 7F4695BC119644B500E82747 /* CalculatorButton3Normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton3Normal.png; path = ../CalculatorButton3Normal.png; sourceTree = ""; }; + 7F4695BD119644B500E82747 /* CalculatorButton3Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton3Highlighted.png; path = ../CalculatorButton3Highlighted.png; sourceTree = ""; }; + 7F4695BE119644B500E82747 /* CalculatorButton4Normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton4Normal.png; path = ../CalculatorButton4Normal.png; sourceTree = ""; }; + 7F4695BF119644B500E82747 /* CalculatorButton4Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CalculatorButton4Highlighted.png; path = ../CalculatorButton4Highlighted.png; sourceTree = ""; }; + 7F4696191196458A00E82747 /* CalculatorBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalculatorBackground.png; sourceTree = ""; }; 7F47897710661CBD002415A2 /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; 7F4A4FE7116A648000FA2019 /* PadRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PadRootViewController.h; sourceTree = ""; }; 7F4A4FE8116A648000FA2019 /* PadRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PadRootViewController.m; sourceTree = ""; }; @@ -774,6 +806,8 @@ 7F87BC9C0ED9B588001C8BC8 /* Security.framework in Frameworks */, 7FB391990EE7991D00AC30D5 /* SystemConfiguration.framework in Frameworks */, 7FE30E141150C8B7004DEA7C /* CFNetwork.framework in Frameworks */, + 7F4695941196439900E82747 /* QuartzCore.framework in Frameworks */, + 7F4695AA119643CE00E82747 /* AudioToolbox.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -810,6 +844,8 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, 7F47897710661CBD002415A2 /* Entitlements.plist */, + 7F4695931196439900E82747 /* QuartzCore.framework */, + 7F4695A9119643CE00E82747 /* AudioToolbox.framework */, ); name = CustomTemplate; sourceTree = ""; @@ -831,6 +867,7 @@ 7FEA5B3F105B6CD2000A12E6 /* ReviewTemplate.html */, 7FE0B9721157B41E00A8B137 /* ImportTemplate.html */, 7FE0B9691157B27000A8B137 /* ImportHelp.html */, + 7F4695B31196448900E82747 /* CalculatorClick.caf */, 7F29EA340ED861B20018C18A /* help */, 7F4C219A10230F1100F17F7D /* ImagesFlags */, 7F4C217510230EF200F17F7D /* Images */, @@ -868,6 +905,10 @@ 7F4A5466116AC58200FA2019 /* ReviewsPane.m */, 7F4A54F4116ACF3A00FA2019 /* ReviewSummaryView.h */, 7F4A54F5116ACF3A00FA2019 /* ReviewSummaryView.m */, + 7F46957D1196436200E82747 /* MovableView.h */, + 7F46957E1196436200E82747 /* MovableView.m */, + 7F46957F1196436200E82747 /* CalculatorView.h */, + 7F4695801196436200E82747 /* CalculatorView.m */, ); name = "iPad Interface"; sourceTree = ""; @@ -875,6 +916,15 @@ 7F4C217510230EF200F17F7D /* Images */ = { isa = PBXGroup; children = ( + 7F4696191196458A00E82747 /* CalculatorBackground.png */, + 7F4695B8119644B500E82747 /* CalculatorButtonNormal.png */, + 7F4695B9119644B500E82747 /* CalculatorButton2Highlighted.png */, + 7F4695BA119644B500E82747 /* CalculatorButton2Normal.png */, + 7F4695BB119644B500E82747 /* CalculatorButtonHighlighted.png */, + 7F4695BC119644B500E82747 /* CalculatorButton3Normal.png */, + 7F4695BD119644B500E82747 /* CalculatorButton3Highlighted.png */, + 7F4695BE119644B500E82747 /* CalculatorButton4Normal.png */, + 7F4695BF119644B500E82747 /* CalculatorButton4Highlighted.png */, 7F4C217E10230EF200F17F7D /* Icon57.png */, 7F82E747116C044D00D5F228 /* Icon72.png */, 7F82E924116C322D00D5F228 /* GraphDetailTop.png */, @@ -887,6 +937,7 @@ 7F82E764116C0C3900D5F228 /* TB_Filter.png */, 7F82E6D1116BF8BC00D5F228 /* TB_Graphs.png */, 7F4A5799116BF1D900FA2019 /* TB_ImportExport.png */, + 7F4695691196403700E82747 /* TB_Calculator.png */, 7F4A54DF116ACAEE00FA2019 /* Background.png */, 7F4A54B8116AC88B00FA2019 /* ReviewBackground.png */, 7F4A51DC116A952600FA2019 /* PaneButtonNormal.png */, @@ -1714,6 +1765,17 @@ 7F82E926116C322D00D5F228 /* GraphDetailTop.png in Resources */, 7F82E927116C322D00D5F228 /* GraphDetailBottom.png in Resources */, 7F06B8EB11714FBF00AFB66D /* TB_About.png in Resources */, + 7F46956A1196403700E82747 /* TB_Calculator.png in Resources */, + 7F4695B41196448900E82747 /* CalculatorClick.caf in Resources */, + 7F4695C1119644B500E82747 /* CalculatorButtonNormal.png in Resources */, + 7F4695C2119644B500E82747 /* CalculatorButton2Highlighted.png in Resources */, + 7F4695C3119644B500E82747 /* CalculatorButton2Normal.png in Resources */, + 7F4695C4119644B500E82747 /* CalculatorButtonHighlighted.png in Resources */, + 7F4695C5119644B500E82747 /* CalculatorButton3Normal.png in Resources */, + 7F4695C6119644B500E82747 /* CalculatorButton3Highlighted.png in Resources */, + 7F4695C7119644B500E82747 /* CalculatorButton4Normal.png in Resources */, + 7F4695C8119644B500E82747 /* CalculatorButton4Highlighted.png in Resources */, + 7F46961A1196458A00E82747 /* CalculatorBackground.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1785,6 +1847,8 @@ 7F4A526B116A9FDA00FA2019 /* DashboardGraphView.m in Sources */, 7F4A5467116AC58200FA2019 /* ReviewsPane.m in Sources */, 7F4A54F6116ACF3A00FA2019 /* ReviewSummaryView.m in Sources */, + 7F4695811196436200E82747 /* MovableView.m in Sources */, + 7F4695821196436200E82747 /* CalculatorView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/CalculatorButton2Highlighted.png b/CalculatorButton2Highlighted.png new file mode 100644 index 00000000..56a751f3 Binary files /dev/null and b/CalculatorButton2Highlighted.png differ diff --git a/CalculatorButton2Normal.png b/CalculatorButton2Normal.png new file mode 100644 index 00000000..381fd1b1 Binary files /dev/null and b/CalculatorButton2Normal.png differ diff --git a/CalculatorButton3Highlighted.png b/CalculatorButton3Highlighted.png new file mode 100644 index 00000000..8a63ad15 Binary files /dev/null and b/CalculatorButton3Highlighted.png differ diff --git a/CalculatorButton3Normal.png b/CalculatorButton3Normal.png new file mode 100644 index 00000000..245dc737 Binary files /dev/null and b/CalculatorButton3Normal.png differ diff --git a/CalculatorButton4Highlighted.png b/CalculatorButton4Highlighted.png new file mode 100644 index 00000000..60aebccc Binary files /dev/null and b/CalculatorButton4Highlighted.png differ diff --git a/CalculatorButton4Normal.png b/CalculatorButton4Normal.png new file mode 100644 index 00000000..4051130c Binary files /dev/null and b/CalculatorButton4Normal.png differ diff --git a/CalculatorButtonHighlighted.png b/CalculatorButtonHighlighted.png new file mode 100644 index 00000000..41066ebd Binary files /dev/null and b/CalculatorButtonHighlighted.png differ diff --git a/CalculatorButtonNormal.png b/CalculatorButtonNormal.png new file mode 100644 index 00000000..ace41c3f Binary files /dev/null and b/CalculatorButtonNormal.png differ diff --git a/CalculatorClick.caf b/CalculatorClick.caf new file mode 100644 index 00000000..8d4d72ca Binary files /dev/null and b/CalculatorClick.caf differ diff --git a/Classes/CalculatorView.h b/Classes/CalculatorView.h new file mode 100644 index 00000000..252e3bc6 --- /dev/null +++ b/Classes/CalculatorView.h @@ -0,0 +1,51 @@ +// +// CalculatorView.h +// AppSales +// +// Created by Ole Zorn on 09.04.10. +// Copyright 2010 omz:software. All rights reserved. +// + +#import +#import +#import "MovableView.h" + +typedef enum TokenType { + TokenTypeOperator, + TokenTypeOperand +} TokenType; + +typedef enum ButtonType { + ButtonTypeUnknown, + ButtonTypeDigit, + ButtonTypeSeparator, + ButtonTypeSign, + ButtonTypeOperator, + ButtonTypeEquals, + ButtonTypeClear +} ButtonType; + +@class CalculatorMO; + +@interface CalculatorView : MovableView { + + SystemSoundID clickSoundID; + UILabel *displayLabel; + + NSMutableArray *stack; + BOOL displaysResult; +} + +- (void)buttonDown:(id)sender; +- (void)buttonPressed:(id)sender; +- (void)enterCalculatorButton:(NSString *)title; +- (void)setDisplay:(NSString *)newDisplay; +- (int)numberOfOperatorsOnStack; +- (int)firstOperatorPrecedence; +- (int)precedenceForOperator:(NSString *)op; +- (void)evaluateStack; +- (TokenType)tokenTypeFor:(NSString *)tokenString; +- (ButtonType)buttonTypeFor:(NSString *)buttonTitle; + + +@end diff --git a/Classes/CalculatorView.m b/Classes/CalculatorView.m new file mode 100644 index 00000000..1121abd3 --- /dev/null +++ b/Classes/CalculatorView.m @@ -0,0 +1,455 @@ +// +// CalculatorView.m +// AppSales +// +// Created by Ole Zorn on 09.04.10. +// Copyright 2010 omz:software. All rights reserved. +// + +#import "CalculatorView.h" + +@implementation CalculatorView + + +- (id)initWithFrame:(CGRect)rect +{ + CGSize calculatorSize = CGSizeMake(280,357); + if ((self = [super initWithFrame:CGRectMake(rect.origin.x, rect.origin.y, calculatorSize.width, calculatorSize.height)])) { + UIImageView *backgroundImageView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, calculatorSize.width, calculatorSize.height)] autorelease]; + backgroundImageView.image = [UIImage imageNamed:@"CalculatorBackground.png"]; + [self addSubview:backgroundImageView]; + + NSMutableArray *buttons = [NSMutableArray array]; + + AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"CalculatorClick" ofType:@"caf"]], &clickSoundID); + + do { + //C, <-, /, x + UIButton *clearButton = [UIButton buttonWithType:UIButtonTypeCustom]; + clearButton.frame = CGRectMake(18, 95, 54, 40); + [clearButton setTitle:@"C" forState:UIControlStateNormal]; + [buttons addObject:clearButton]; + + UIButton *signButton = [UIButton buttonWithType:UIButtonTypeCustom]; + signButton.frame = CGRectMake(81, 95, 54, 40); + [signButton setTitle:@"±" forState:UIControlStateNormal]; + [buttons addObject:signButton]; + + UIButton *divideButton = [UIButton buttonWithType:UIButtonTypeCustom]; + divideButton.frame = CGRectMake(144, 95, 54, 40); + [divideButton setTitle:@"÷" forState:UIControlStateNormal]; + [buttons addObject:divideButton]; + + UIButton *multiplyButton = [UIButton buttonWithType:UIButtonTypeCustom]; + multiplyButton.frame = CGRectMake(207, 95, 54, 40); + [multiplyButton setTitle:@"×" forState:UIControlStateNormal]; + [buttons addObject:multiplyButton]; + + //7, 8, 9, - + UIButton *sevenButton = [UIButton buttonWithType:UIButtonTypeCustom]; + sevenButton.frame = CGRectMake(18, 145, 54, 40); + [sevenButton setTitle:@"7" forState:UIControlStateNormal]; + [buttons addObject:sevenButton]; + + UIButton *eightButton = [UIButton buttonWithType:UIButtonTypeCustom]; + eightButton.frame = CGRectMake(81, 145, 54, 40); + [eightButton setTitle:@"8" forState:UIControlStateNormal]; + [buttons addObject:eightButton]; + + UIButton *nineButton = [UIButton buttonWithType:UIButtonTypeCustom]; + nineButton.frame = CGRectMake(144, 145, 54, 40); + [nineButton setTitle:@"9" forState:UIControlStateNormal]; + [buttons addObject:nineButton]; + + UIButton *minusButton = [UIButton buttonWithType:UIButtonTypeCustom]; + minusButton.frame = CGRectMake(207, 145, 54, 40); + [minusButton setTitle:@"–" forState:UIControlStateNormal]; + [buttons addObject:minusButton]; + + //4, 5, 6, +: + UIButton *fourButton = [UIButton buttonWithType:UIButtonTypeCustom]; + fourButton.frame = CGRectMake(18, 195, 54, 40); + [fourButton setTitle:@"4" forState:UIControlStateNormal]; + [buttons addObject:fourButton]; + + UIButton *fiveButton = [UIButton buttonWithType:UIButtonTypeCustom]; + fiveButton.frame = CGRectMake(81, 195, 54, 40); + [fiveButton setTitle:@"5" forState:UIControlStateNormal]; + [buttons addObject:fiveButton]; + + UIButton *sixButton = [UIButton buttonWithType:UIButtonTypeCustom]; + sixButton.frame = CGRectMake(144, 195, 54, 40); + [sixButton setTitle:@"6" forState:UIControlStateNormal]; + [buttons addObject:sixButton]; + + UIButton *plusButton = [UIButton buttonWithType:UIButtonTypeCustom]; + plusButton.frame = CGRectMake(207, 195, 54, 40); + [plusButton setTitle:@"+" forState:UIControlStateNormal]; + [buttons addObject:plusButton]; + + //1, 2, 3: + UIButton *oneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + oneButton.frame = CGRectMake(18, 245, 54, 40); + [oneButton setTitle:@"1" forState:UIControlStateNormal]; + [buttons addObject:oneButton]; + + UIButton *twoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + twoButton.frame = CGRectMake(81, 245, 54, 40); + [twoButton setTitle:@"2" forState:UIControlStateNormal]; + [buttons addObject:twoButton]; + + UIButton *threeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + threeButton.frame = CGRectMake(144, 245, 54, 40); + [threeButton setTitle:@"3" forState:UIControlStateNormal]; + [buttons addObject:threeButton]; + + UIButton *equalsButton = [UIButton buttonWithType:UIButtonTypeCustom]; + equalsButton.frame = CGRectMake(207, 245, 54, 92); + [equalsButton setTitle:@"=" forState:UIControlStateNormal]; + [buttons addObject:equalsButton]; + + //0, .: + UIButton *zeroButton = [UIButton buttonWithType:UIButtonTypeCustom]; + zeroButton.frame = CGRectMake(18, 297, 117, 40); + [zeroButton setTitle:@"0" forState:UIControlStateNormal]; + [buttons addObject:zeroButton]; + + UIButton *dotButton = [UIButton buttonWithType:UIButtonTypeCustom]; + dotButton.frame = CGRectMake(144, 297, 54, 40); + [dotButton setTitle:@"." forState:UIControlStateNormal]; + [buttons addObject:dotButton]; + } while (NO); + + UIImage *buttonImageNormal = [[UIImage imageNamed:@"CalculatorButtonNormal.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageHighlighted = [[UIImage imageNamed:@"CalculatorButtonHighlighted.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageNormal2 = [[UIImage imageNamed:@"CalculatorButton2Normal.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageHighlighted2 = [[UIImage imageNamed:@"CalculatorButton2Highlighted.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageNormal3 = [[UIImage imageNamed:@"CalculatorButton3Normal.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageHighlighted3 = [[UIImage imageNamed:@"CalculatorButton3Highlighted.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageNormal4 = [[UIImage imageNamed:@"CalculatorButton4Normal.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + UIImage *buttonImageHighlighted4 = [[UIImage imageNamed:@"CalculatorButton4Highlighted.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; + + for (UIButton *button in buttons) { + button.titleLabel.font = [UIFont fontWithName:@"Verdana" size:20.0]; + [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + NSString *title = button.titleLabel.text; + if ([title isEqual:@"="]) { + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];; + [button setBackgroundImage:buttonImageNormal4 forState:UIControlStateNormal]; + [button setBackgroundImage:buttonImageHighlighted4 forState:UIControlStateHighlighted]; + } + else if ([title isEqual:@"C"]) { + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];; + [button setBackgroundImage:buttonImageNormal3 forState:UIControlStateNormal]; + [button setBackgroundImage:buttonImageHighlighted3 forState:UIControlStateHighlighted]; + } else if ([title isEqual:@"0"] || [title isEqual:@"."] || [title intValue] != 0) { + [button setBackgroundImage:buttonImageNormal forState:UIControlStateNormal]; + [button setBackgroundImage:buttonImageHighlighted forState:UIControlStateHighlighted]; + } else { + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [button setBackgroundImage:buttonImageNormal2 forState:UIControlStateNormal]; + [button setBackgroundImage:buttonImageHighlighted2 forState:UIControlStateHighlighted]; + } + [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; + [button addTarget:self action:@selector(buttonDown:) forControlEvents:UIControlEventTouchDown]; + [self addSubview:button]; + } + + displayLabel = [[[UILabel alloc] initWithFrame:CGRectMake(17, 20, 244, 44)] autorelease]; + displayLabel.text = @"0"; + + displayLabel.textAlignment = UITextAlignmentRight; + displayLabel.font = [UIFont fontWithName:@"Verdana" size:40]; + displayLabel.backgroundColor = [UIColor clearColor]; + displayLabel.adjustsFontSizeToFitWidth = YES; + displayLabel.lineBreakMode = UILineBreakModeHeadTruncation; + displayLabel.minimumFontSize = 17.0; + [self addSubview:displayLabel]; + + UIButton *displayButton = [UIButton buttonWithType:UIButtonTypeCustom]; + displayButton.frame = CGRectMake(13, 12, 253, 64); + [displayButton addTarget:self action:@selector(displayTapped:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:displayButton]; + + stack = [NSMutableArray new]; + [stack addObject:displayLabel.text]; + } + return self; +} + + +#pragma mark - +#pragma mark UI Actions +- (void)copy:(id)sender +{ + [[UIPasteboard generalPasteboard] setString:displayLabel.text]; +} + +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (void)displayTapped:(id)sender +{ + [self.superview bringSubviewToFront:self]; + [self becomeFirstResponder]; + + [[UIMenuController sharedMenuController] setTargetRect:[sender frame] inView:self]; + [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES]; +} + +- (void)buttonDown:(id)sender +{ + AudioServicesPlaySystemSound(clickSoundID); + [self.superview bringSubviewToFront:self]; +} + +- (void)buttonPressed:(id)sender +{ + UIButton *button = (UIButton *)sender; + NSString *title = button.titleLabel.text; + [self enterCalculatorButton:title]; +} + +- (void)setDisplay:(NSString *)newDisplay +{ + displayLabel.text = newDisplay; +} + +#pragma mark - +#pragma mark Calculator Engine + +- (void)enterCalculatorButton:(NSString *)title +{ + NSString *currentDisplay = [[[stack lastObject] retain] autorelease]; + NSString *newDisplay = nil; + TokenType lastTokenType = [self tokenTypeFor:[stack lastObject]]; + ButtonType buttonType = [self buttonTypeFor:title]; + + if (buttonType == ButtonTypeClear) { + [stack removeAllObjects]; + [stack addObject:@"0"]; + [self setDisplay:@"0"]; + } + if ([currentDisplay isEqual:NSLocalizedString(@"Error",nil)]) { + return; + } + if (buttonType == ButtonTypeDigit) { + if (lastTokenType == TokenTypeOperand) { + if (displaysResult || [currentDisplay isEqual:@"0"]) { + newDisplay = title; + } else { + newDisplay = [currentDisplay stringByAppendingString:title]; + } + [stack removeLastObject]; + [stack addObject:newDisplay]; + [self setDisplay:newDisplay]; + } else { //Operator + [stack addObject:title]; + [self setDisplay:title]; + } + displaysResult = NO; + } + if (buttonType == ButtonTypeSign) { + if (lastTokenType == TokenTypeOperand) { + if ([currentDisplay doubleValue] != 0) { + if ([[currentDisplay substringToIndex:1] isEqual:@"-"]) { + newDisplay = [currentDisplay substringFromIndex:1]; + } else { + newDisplay = [NSString stringWithFormat:@"-%@", currentDisplay]; + } + [stack removeLastObject]; + [stack addObject:newDisplay]; + [self setDisplay:newDisplay]; + } + } + } + if (buttonType == ButtonTypeSeparator) { + if (lastTokenType == TokenTypeOperator) { + [stack addObject:@"0."]; + [self setDisplay:@"0."]; + } else { + if ([currentDisplay rangeOfString:@"."].location == NSNotFound) { + newDisplay = [currentDisplay stringByAppendingString:@"."]; + [stack removeLastObject]; + [stack addObject:newDisplay]; + [self setDisplay:newDisplay]; + } + } + displaysResult = NO; + } + if (buttonType == ButtonTypeOperator) { + if (lastTokenType == TokenTypeOperand) { + int currentOpPrecedence = [self precedenceForOperator:title]; + if ([self numberOfOperatorsOnStack] > 1 || [self firstOperatorPrecedence] >= currentOpPrecedence) { + [self evaluateStack]; + [self setDisplay:[stack lastObject]]; + } + [stack addObject:title]; + } else { + //Another operator is already on the stack, replace it + [stack removeLastObject]; + [stack addObject:title]; + } + displaysResult = NO; + } + if (buttonType == ButtonTypeEquals) { + [self evaluateStack]; + [self setDisplay:[stack lastObject]]; + displaysResult = YES; + } + +} + +- (void)evaluateStack +{ + if ([self tokenTypeFor:[stack lastObject]] == TokenTypeOperator) { + [stack removeLastObject]; + } + if ([stack count] == 3) { + NSString *operand1 = [stack objectAtIndex:0]; + NSString *operator = [stack objectAtIndex:1]; + NSString *operand2 = [stack objectAtIndex:2]; + double n1 = [operand1 doubleValue]; + double n2 = [operand2 doubleValue]; + double result = 0.0; + BOOL error = NO; + if ([operator isEqual:@"+"]) { + result = n1 + n2; + } else if ([operator isEqual:@"÷"]) { + if (n2 == 0) { + error = YES; + } else { + result = n1 / n2; + } + } else if ([operator isEqual:@"×"]) { + result = n1 * n2; + } else { + result = n1 - n2; + } + if (!error) { + NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease]; + [numberFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en-us"] autorelease]]; + [numberFormatter setMinimumFractionDigits:0]; + [numberFormatter setMaximumFractionDigits:10]; + [numberFormatter setMinimumIntegerDigits:1]; + NSString *resultString = [numberFormatter stringFromNumber:[NSNumber numberWithDouble:result]]; + [stack removeAllObjects]; + [stack addObject:resultString]; + } else { + [stack removeAllObjects]; + [stack addObject:NSLocalizedString(@"Error",nil)]; + } + } + if ([stack count] == 5) { + double n1 = [[stack objectAtIndex:0] doubleValue]; + double n2 = [[stack objectAtIndex:2] doubleValue]; + double n3 = [[stack objectAtIndex:4] doubleValue]; + NSString *operator1 = [stack objectAtIndex:1]; + NSString *operator2 = [stack objectAtIndex:3]; + double partialResult = 0.0; + BOOL error = NO; + if ([operator2 isEqual:@"×"]) { + partialResult = n2 * n3; + } else { + if (n3 == 0) { + error = YES; + } else { + partialResult = n2 / n3; + } + } + double result; + if ([operator1 isEqual:@"+"]) { + result = n1 + partialResult; + } else { + result = n1 - partialResult; + } + if (!error) { + NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease]; + [numberFormatter setMinimumFractionDigits:0]; + [numberFormatter setMaximumFractionDigits:10]; + [numberFormatter setMinimumIntegerDigits:1]; + NSString *resultString = [numberFormatter stringFromNumber:[NSNumber numberWithDouble:result]]; + [stack removeAllObjects]; + [stack addObject:resultString]; + } else { + [stack removeAllObjects]; + [stack addObject:NSLocalizedString(@"Error",nil)]; + } + } +} + +- (int)firstOperatorPrecedence +{ + for (NSString *token in stack) { + if ([self tokenTypeFor:token] == TokenTypeOperator) { + if ([token isEqual:@"+"] || [token isEqual:@"–"]) { + return 1; + } else { + return 2; + } + } + } + return 0; +} + +- (int)precedenceForOperator:(NSString *)op +{ + if ([op isEqual:@"+"] || [op isEqual:@"–"]) { + return 1; + } + return 2; +} + +- (int)numberOfOperatorsOnStack +{ + int c = 0; + for (NSString *token in stack) { + if ([self tokenTypeFor:token] == TokenTypeOperator) { + c++; + } + } + return c; +} + +- (TokenType)tokenTypeFor:(NSString *)tokenString +{ + if ([tokenString isEqual:@"+"] || [tokenString isEqual:@"–"] || [tokenString isEqual:@"÷"] || [tokenString isEqual:@"×"]) { + return TokenTypeOperator; + } + return TokenTypeOperand; +} + +- (ButtonType)buttonTypeFor:(NSString *)buttonTitle +{ + int i = [buttonTitle intValue]; + if (i != 0 || [buttonTitle isEqual:@"0"]) { + return ButtonTypeDigit; + } + if ([buttonTitle isEqual:@"."]) { + return ButtonTypeSeparator; + } + if ([buttonTitle isEqual:@"±"]) { + return ButtonTypeSign; + } + if ([buttonTitle isEqual:@"+"] || [buttonTitle isEqual:@"–"] || [buttonTitle isEqual:@"÷"] || [buttonTitle isEqual:@"×"]) { + return ButtonTypeOperator; + } + if ([buttonTitle isEqual:@"="]) { + return ButtonTypeEquals; + } + if ([buttonTitle isEqual:@"C"]) { + return ButtonTypeClear; + } + return ButtonTypeUnknown; +} + +- (void)dealloc +{ + [stack release]; + [super dealloc]; +} + + +@end diff --git a/Classes/MovableView.h b/Classes/MovableView.h new file mode 100644 index 00000000..231d74a6 --- /dev/null +++ b/Classes/MovableView.h @@ -0,0 +1,18 @@ +// +// MovableView.h +// AppSales +// +// Created by Ole Zorn on 09.04.10. +// Copyright 2010 omz:software. All rights reserved. +// + +#import +#import + +@interface MovableView : UIView { + +} + +- (void)pan:(UIPanGestureRecognizer *)recognizer; + +@end diff --git a/Classes/MovableView.m b/Classes/MovableView.m new file mode 100644 index 00000000..5bb1ab2e --- /dev/null +++ b/Classes/MovableView.m @@ -0,0 +1,50 @@ +// +// MovableView.m +// AppSales +// +// Created by Ole Zorn on 09.04.10. +// Copyright 2010 omz:software. All rights reserved. +// + +#import "MovableView.h" + + +@implementation MovableView + + +- (id)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) { + UIPanGestureRecognizer *recognizer = [[[NSClassFromString(@"UIPanGestureRecognizer") alloc] initWithTarget:self action:@selector(pan:)] autorelease]; + [self addGestureRecognizer:recognizer]; + } + return self; +} + +- (void)pan:(UIPanGestureRecognizer *)recognizer +{ + UIGestureRecognizerState state = recognizer.state; + if (state == UIGestureRecognizerStateBegan) { + [self.superview bringSubviewToFront:self]; + } + else if (state == UIGestureRecognizerStateChanged) { + CGPoint translation = [recognizer translationInView:self.superview]; + + CGPoint center = self.center; + CGPoint newCenter = CGPointMake(center.x + translation.x, center.y + translation.y); + self.center = newCenter; + + [recognizer setTranslation:CGPointZero inView:self.superview]; + } + else if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateFailed || state == UIGestureRecognizerStateCancelled) { + + } +} + +- (void)dealloc +{ + [super dealloc]; +} + + +@end diff --git a/Classes/PadRootViewController.h b/Classes/PadRootViewController.h index d59d6612..42427f82 100644 --- a/Classes/PadRootViewController.h +++ b/Classes/PadRootViewController.h @@ -8,7 +8,7 @@ #import -@class DashboardView, ReviewsPane; +@class DashboardView, ReviewsPane, CalculatorView; @interface PadRootViewController : UIViewController { @@ -22,10 +22,11 @@ UIBarButtonItem *filterItem; UIActionSheet *filterSheet; - DashboardView *dailyDashboardView; DashboardView *weeklyDashboardView; ReviewsPane *reviewsPane; + + CalculatorView *calculator; } @property (nonatomic, retain) UIToolbar *toolbar; diff --git a/Classes/PadRootViewController.m b/Classes/PadRootViewController.m index f0010eb1..2f60e638 100644 --- a/Classes/PadRootViewController.m +++ b/Classes/PadRootViewController.m @@ -17,6 +17,7 @@ #import "ReviewsPane.h" #import "App.h" #import "HelpBrowser.h" +#import "CalculatorView.h" @implementation PadRootViewController @@ -52,11 +53,13 @@ - (void)loadView UIBarButtonItem *spaceItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil] autorelease]; spaceItem.width = 32.0; + UIBarButtonItem *calculatorItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"TB_Calculator.png"] style:UIBarButtonItemStylePlain target:self action:@selector(toggleCalculator:)] autorelease]; + UIBarButtonItem *graphTypeItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"TB_Graphs.png"] style:UIBarButtonItemStylePlain target:self action:@selector(selectGraphType:)] autorelease]; self.filterItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"TB_Filter.png"] style:UIBarButtonItemStylePlain target:self action:@selector(selectFilter:)] autorelease]; self.toolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, 44)] autorelease]; toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth; - toolbar.items = [NSArray arrayWithObjects:refreshItem, flexItem, activityIndicatorItem, statusItem, flexItem, graphTypeItem, spaceItem, filterItem, spaceItem, spaceItem, spaceItem, importExportItem, spaceItem, settingsItem, spaceItem, aboutItem, nil]; + toolbar.items = [NSArray arrayWithObjects:refreshItem, flexItem, activityIndicatorItem, statusItem, flexItem, calculatorItem, spaceItem, spaceItem, graphTypeItem, spaceItem, filterItem, spaceItem, spaceItem, spaceItem, importExportItem, spaceItem, settingsItem, spaceItem, aboutItem, nil]; [self.view addSubview:toolbar]; self.dailyDashboardView = [[[DashboardView alloc] initWithFrame:CGRectMake(0, 47, 748, 320)] autorelease]; @@ -120,6 +123,33 @@ - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInte } } +- (void)toggleCalculator:(id)sender +{ + if (!calculator) { + CGSize calculatorSize = CGSizeMake(280,357); + CGRect calculatorFrame = CGRectMake((int)(self.view.bounds.size.width/2 - calculatorSize.width/2), (int)(self.view.bounds.size.height/2 - calculatorSize.height/2), calculatorSize.width, calculatorSize.height); + calculator = [[[CalculatorView alloc] initWithFrame:calculatorFrame] autorelease]; + calculator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; + [self.view addSubview:calculator]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; + animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity]; + animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1.0)]; + animation.duration = 0.15; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + animation.autoreverses = YES; + animation.removedOnCompletion = YES; + [calculator.layer addAnimation:animation forKey:@"bounce"]; + } else { + [UIView beginAnimations:@"hideCalculator" context:nil]; + calculator.transform = CGAffineTransformMakeScale(0.5,0.5); + calculator.alpha = 0.0; + [UIView commitAnimations]; + [calculator performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.5]; + calculator = nil; + } +} + - (void)selectGraphType:(id)sender { if (!self.graphTypeSheet) { diff --git a/Images/CalculatorBackground.png b/Images/CalculatorBackground.png new file mode 100644 index 00000000..acea57af Binary files /dev/null and b/Images/CalculatorBackground.png differ diff --git a/Images/TB_Calculator.png b/Images/TB_Calculator.png new file mode 100644 index 00000000..e5130838 Binary files /dev/null and b/Images/TB_Calculator.png differ