Skip to content

Instantly share code, notes, and snippets.

@amosgyamfi
Last active September 22, 2024 06:10
Show Gist options
  • Save amosgyamfi/30b41fbae0029cd333bc03055d2c392c to your computer and use it in GitHub Desktop.
Save amosgyamfi/30b41fbae0029cd333bc03055d2c392c to your computer and use it in GitHub Desktop.
//
// BasiciOSCalculator.swift
import SwiftUI
struct BasiciOSCalculator: View {
@State private var displayValue: String = "0"
@State private var currentOperation: Operation? = nil
@State private var previousValue: Double? = nil
@State private var shouldResetDisplay: Bool = false
enum Operation {
case add, subtract, multiply, divide, percentage
}
var body: some View {
Button {
// Main button action (if needed)
} label: {
VStack(spacing: 0) {
TextField("0", text: $displayValue)
.font(.system(size: 64))
.foregroundColor(.white)
.frame(maxWidth: .infinity, alignment: .trailing)
.padding()
.disabled(true)
VStack(spacing: 1) {
HStack(spacing: 1) {
Button(action: { /* Show menu */ }) {
Image(systemName: "list.bullet")
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary.opacity(0.5))
}
.contextMenu {
Button("Basic") { }
Button("Scientific") { }
Button("Math Notes") { }
Toggle("Convert", isOn: .constant(false))
}
Button("AC") { clear() }
.foregroundStyle(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary.opacity(0.5))
Button("%") { performOperation(.percentage) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary.opacity(0.5))
Button("÷") { performOperation(.divide) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.orange)
}
HStack(spacing: 1) {
ForEach(["7", "8", "9"], id: \.self) { number in
Button(number) { appendNumber(number) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary)
}
Button("×") { performOperation(.multiply) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.orange)
}
HStack(spacing: 1) {
ForEach(["4", "5", "6"], id: \.self) { number in
Button(number) { appendNumber(number) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary)
}
Button("-") { performOperation(.subtract) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.orange)
}
HStack(spacing: 1) {
ForEach(["1", "2", "3"], id: \.self) { number in
Button(number) { appendNumber(number) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary)
}
Button("+") { performOperation(.add) }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.orange)
}
HStack(spacing: 1) {
Button("0") { appendNumber("0") }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary)
Button(".") { appendDecimal() }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.secondary)
Button("=") { calculateResult() }
.foregroundColor(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.orange)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
}
.buttonStyle(.plain)
}
private func appendNumber(_ number: String) {
if shouldResetDisplay {
displayValue = number
shouldResetDisplay = false
} else {
displayValue = displayValue == "0" ? number : displayValue + number
}
}
private func appendDecimal() {
if !displayValue.contains(".") {
displayValue += "."
}
}
private func clear() {
displayValue = "0"
currentOperation = nil
previousValue = nil
shouldResetDisplay = false
}
private func performOperation(_ operation: Operation) {
if let value = Double(displayValue) {
if let previous = previousValue, let current = currentOperation {
let result = calculate(previous, current, value)
displayValue = formatResult(result)
previousValue = result
} else {
previousValue = value
}
}
currentOperation = operation
shouldResetDisplay = true
}
private func calculateResult() {
if let value = Double(displayValue), let previous = previousValue, let operation = currentOperation {
let result = calculate(previous, operation, value)
displayValue = formatResult(result)
previousValue = nil
currentOperation = nil
}
}
private func calculate(_ a: Double, _ operation: Operation, _ b: Double) -> Double {
switch operation {
case .add: return a + b
case .subtract: return a - b
case .multiply: return a * b
case .divide: return b != 0 ? a / b : Double.nan
case .percentage: return a * (b / 100)
}
}
private func formatResult(_ result: Double) -> String {
return result.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", result) : String(result)
}
}
#Preview {
BasiciOSCalculator()
.preferredColorScheme(.dark)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment