Skip to content

Commit

Permalink
Improved code readability, recursive parentheses on submit, screenshots
Browse files Browse the repository at this point in the history
  • Loading branch information
antingle committed May 3, 2022
1 parent 31843f0 commit a66f68b
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 85 deletions.
4 changes: 2 additions & 2 deletions Calculator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 0.6.0;
MARKETING_VERSION = 0.7.0;
PRODUCT_BUNDLE_IDENTIFIER = anthonyingle.Calculator;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down Expand Up @@ -391,7 +391,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 0.6.0;
MARKETING_VERSION = 0.7.0;
PRODUCT_BUNDLE_IDENTIFIER = anthonyingle.Calculator;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
8 changes: 8 additions & 0 deletions Calculator/Views/ButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct ButtonView: View {

var body: some View {
VStack {

// MARK: - Row 1
HStack {
Button("C") {
expression = ""
Expand Down Expand Up @@ -67,6 +69,7 @@ struct ButtonView: View {
}.calcButton()
}

// MARK: - Row 2
HStack {
Button("-") {
expression += "-"
Expand Down Expand Up @@ -116,6 +119,7 @@ struct ButtonView: View {
}.calcButton()
}

// MARK: - Row 3
HStack {
Button ("EE") {
expression += "E"
Expand Down Expand Up @@ -143,6 +147,7 @@ struct ButtonView: View {
}.calcButton()
}

// MARK: - Row 4
HStack {
Button ("sin(x)") {
expression += "sin("
Expand All @@ -160,6 +165,7 @@ struct ButtonView: View {
}.calcButton()
}

// MARK: - Row 5
HStack {
Button ("asin(x)") {
expression += "asin("
Expand All @@ -180,6 +186,7 @@ struct ButtonView: View {
.frame(maxWidth: 600)
}

// MARK: - Helper Functions
private func addAnswer() {
if (!historyStore.history.isEmpty)
{
Expand All @@ -188,6 +195,7 @@ struct ButtonView: View {
}
}

// MARK: - Preview
struct Previews_ButtonView_Previews: PreviewProvider {
static var previews: some View {
ButtonView(expression: .constant(""), historyIndex: .constant(-1))
Expand Down
150 changes: 82 additions & 68 deletions Calculator/Views/CalculatorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,84 +8,29 @@
import SwiftUI

struct CalculatorView: View {
@EnvironmentObject var historyStore: HistoryStore
@State private var expression: String = ""
@State private var solution: Double = 0.0
@EnvironmentObject var historyStore: HistoryStore // history of previous calculations
@State private var expression: String = "" // expression being typed
@State private var solution: Double = 0.0 // solution after expression evalutation
@State private var historyIndex: Int = -1 // keeps track of place in history when cycling
@State private var expressionIsValid: Bool = false // used to show live solution

var body: some View {

VStack {
// MARK: - History View
// A view to show all previous solutions and expressions
HistoryView(expression: $expression, historyIndex: $historyIndex)

// MARK: - TextField View
// An NSTextField wrapped as a SwiftUI view
CustomMacTextView(placeholderText: "Calculate", text: $expression,

// on ENTER key press
onSubmit: {
do {
historyIndex = -1
solution = try evaluateExpression(expression)

// insert item into history
withAnimation(.spring()) {
let historyItem = History(expression: expression, solution: solution.removeZerosFromEnd())
historyStore.history.insert(historyItem, at: 0)
}
expression = ""
solution = 0

// save history
HistoryStore.save(history: historyStore.history) { result in
if case .failure(let error) = result {
fatalError(error.localizedDescription)
}
}
}
catch {
solution = 0
}

},
onSubmit: onExpressionSubmit, // on ENTER key press
// On every update of the textfield by keyboard
onTextChange: { newExpression in
historyIndex = -1 // reset history counter when keyboard used
},

// on UP ARROW key
onMoveUp: {
// check that history array is not empty and history index does not go out of bounds
if (!historyStore.history.isEmpty && historyIndex < historyStore.history.count - 1)
{
historyIndex += 1

// if incrementing history, remove the number of characters of previous addition
if historyIndex > 0 {
expression.removeLast(historyStore.history[historyIndex - 1].solution.count)
}
expression += historyStore.history[historyIndex].solution
}
},

// on DOWN ARROW key
onMoveDown: {
if (!historyStore.history.isEmpty)
{
// check if UP ARROW has been pressed yet
if historyIndex != -1 {
// if decrementing history, remove the number of characters of previous addition
expression.removeLast(historyStore.history[historyIndex].solution.count)
historyIndex -= 1

// if we are not at the beginning of history, add the next solution in
if historyIndex != -1 {
expression += historyStore.history[historyIndex].solution
}
}
}
})
// reset history counter when keyboard used
onTextChange: { _ in historyIndex = -1 },
onMoveUp: onMoveCursorUp, // on UP ARROW key
onMoveDown: onMoveCursorDown) // on DOWN ARROW key

.frame(height: 27) // MARK TODO: Make height-adjustable

// will always run on change of expression variable
Expand All @@ -107,24 +52,93 @@ struct CalculatorView: View {
expressionIsValid = true
}
catch {
print(error)
expressionIsValid = false
solution = 0
}
})

// Live solution shower
// MARK: - Live Solution View
Text(expressionIsValid ? solution.removeZerosFromEnd() : " ")
.font(.caption)
.frame(maxWidth: .infinity, alignment: .trailing)
.foregroundColor(.secondary)

// MARK: - Button View
// A view for all the buttons at the bottom
ButtonView(expression: $expression, historyIndex: $historyIndex)
}
}

// MARK: - Textfield Functions
fileprivate func onExpressionSubmit() {
do {
historyIndex = -1
solution = try evaluateExpression(expression)

// insert item into history
withAnimation(.spring()) {
let historyItem = History(expression: expression, solution: solution.removeZerosFromEnd())
historyStore.history.insert(historyItem, at: 0)
}
expression = ""
solution = 0

// save history
HistoryStore.save(history: historyStore.history) { result in
if case .failure(let error) = result {
fatalError(error.localizedDescription)
}
}
}
catch {
// recursively run submit if simply missing parentheses
if ("\(error)" == "Missing `)`")
{
expression += ")"
onExpressionSubmit()
}
else if ("\(error)" == "Missing `(`")
{
expression += "("
onExpressionSubmit()
}
solution = 0
}
}

fileprivate func onMoveCursorUp() {
// check that history array is not empty and history index does not go out of bounds
if (!historyStore.history.isEmpty && historyIndex < historyStore.history.count - 1)
{
historyIndex += 1

// if incrementing history, remove the number of characters of previous addition
if historyIndex > 0 {
expression.removeLast(historyStore.history[historyIndex - 1].solution.count)
}
expression += historyStore.history[historyIndex].solution
}
}

fileprivate func onMoveCursorDown() {
if (!historyStore.history.isEmpty)
{
// check if UP ARROW has been pressed yet
if historyIndex != -1 {
// if decrementing history, remove the number of characters of previous addition
expression.removeLast(historyStore.history[historyIndex].solution.count)
historyIndex -= 1

// if we are not at the beginning of history, add the next solution in
if historyIndex != -1 {
expression += historyStore.history[historyIndex].solution
}
}
}
}
}

// MARK: - Preview
struct Previews_CalculatorView_Previews: PreviewProvider {
static var previews: some View {
CalculatorView()
Expand Down
5 changes: 5 additions & 0 deletions Calculator/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct ContentView: View {

CalculatorView()

// MARK: - Bottom Bar
HStack {
Text("Menu Bar Calc")
.font(.headline)
Expand All @@ -33,6 +34,8 @@ struct ContentView: View {
.popover(isPresented: $showingSettings, content: {
SettingsView().padding()
})

// Open in separate window
Button {
NSApp.sendAction(#selector(AppDelegate.openCalculatorWindow), to: nil, from:nil)
} label: {
Expand All @@ -46,6 +49,7 @@ struct ContentView: View {
.padding([.horizontal, .bottom])
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
// Load history on from save on launch
HistoryStore.load { result in
switch result {
case .failure(let error):
Expand All @@ -59,6 +63,7 @@ struct ContentView: View {
}
}

// MARK: - Preview
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
Expand Down
14 changes: 4 additions & 10 deletions Calculator/Views/CustomMacTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ struct CustomMacTextView: NSViewRepresentable {

var onMoveUp : () -> Void = {}
var onMoveDown : () -> Void = {}
fileprivate let scrollView = PlaceholderNSTextView.scrollableTextView()

func makeCoordinator() -> Coordinator {
Coordinator(self)
}

func makeNSView(context: Context) -> NSScrollView {
let theTextView = PlaceholderNSTextView.scrollableTextView()
let textView = (theTextView.documentView as! PlaceholderNSTextView)
let textView = (scrollView.documentView as! PlaceholderNSTextView)
textView.delegate = context.coordinator
textView.string = text
textView.drawsBackground = false
textView.font = font
textView.allowsUndo = true
textView.placeholderText = placeholderText
theTextView.hasVerticalScroller = false
scrollView.hasVerticalScroller = false

return theTextView
return scrollView
}

func updateNSView(_ view: NSScrollView, context: Context) {
Expand All @@ -55,7 +55,6 @@ extension CustomMacTextView {
class Coordinator: NSObject, NSTextViewDelegate {

var parent: CustomMacTextView
var affectedCharRange: NSRange?

init(_ parent: CustomMacTextView) {
self.parent = parent
Expand Down Expand Up @@ -89,11 +88,6 @@ extension CustomMacTextView {
self.parent.onSubmit()
}


func textView(_ textView: NSTextView, shouldChangeTextIn affectedCharRange: NSRange, replacementString: String?) -> Bool {
return true
}

// handles commands
func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if (commandSelector == #selector(NSResponder.insertNewline(_:))) {
Expand Down
Loading

0 comments on commit a66f68b

Please sign in to comment.