Convertes to Swift and SwiftUI
This commit is contained in:
425
iOS/MonsterCards/Views/EditMonster.swift
Normal file
425
iOS/MonsterCards/Views/EditMonster.swift
Normal file
@@ -0,0 +1,425 @@
|
||||
//
|
||||
// EditMonster.swift
|
||||
// MonsterCards
|
||||
//
|
||||
// Created by Tom Hicks on 1/16/21.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import SwiftUI
|
||||
|
||||
struct EditMonster: View {
|
||||
// TODO: add challengeRating/challengeRatingEnum and customChallengeRating maybe in basicInfo
|
||||
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
|
||||
@Environment(\.managedObjectContext) private var viewContext
|
||||
|
||||
var monster: Monster
|
||||
|
||||
@State private var monsterName: String = ""
|
||||
@State private var monsterSize: String = ""
|
||||
@State private var monsterType: String = ""
|
||||
@State private var monsterSubtype: String = ""
|
||||
@State private var monsterAlignment: String = ""
|
||||
@State private var monsterHitDice: Int64 = 0
|
||||
@State private var monsterHasCustomHP: Bool = false
|
||||
@State private var monsterCustomHP: String = ""
|
||||
@State private var monsterArmorType: String = ""
|
||||
@State private var monsterHasShield: Bool = false
|
||||
@State private var monsterNaturalArmorBonus: Int64 = 0
|
||||
@State private var monsterCustomArmor: String = ""
|
||||
@State private var monsterBaseSpeed: Int64 = 0
|
||||
@State private var monsterBurrowSpeed: Int64 = 0
|
||||
@State private var monsterClimbSpeed: Int64 = 0
|
||||
@State private var monsterFlySpeed: Int64 = 0
|
||||
@State private var monsterCanHover: Bool = false
|
||||
@State private var monsterSwimSpeed: Int64 = 0
|
||||
@State private var monsterHasCustomSpeed: Bool = false
|
||||
@State private var monsterCustomSpeed: String = ""
|
||||
@State private var monsterStrengthScore: Int64 = 10
|
||||
@State private var monsterDexterityScore: Int64 = 10
|
||||
@State private var monsterConstitutionScore: Int64 = 10
|
||||
@State private var monsterIntelligenceScore: Int64 = 10
|
||||
@State private var monsterWisdomScore: Int64 = 10
|
||||
@State private var monsterCharismaScore: Int64 = 10
|
||||
|
||||
@State private var monsterStrengthSavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterStrengthSavingThrowAdvantage: AdvantageType = .none
|
||||
@State private var monsterDexteritySavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterDexteritySavingThrowAdvantage: AdvantageType = .none
|
||||
@State private var monsterConstitutionSavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterConstitutionSavingThrowAdvantage: AdvantageType = .none
|
||||
@State private var monsterIntelligenceSavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterIntelligenceSavingThrowAdvantage: AdvantageType = .none
|
||||
@State private var monsterWisdomSavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterWisdomSavingThrowAdvantage: AdvantageType = .none
|
||||
@State private var monsterCharismaSavingThrowProficiency: ProficiencyType = .none
|
||||
@State private var monsterCharismaSavingThrowAdvantage: AdvantageType = .none
|
||||
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section(header: Text("Basic Info")) {
|
||||
// Editable Text field bound to monster.name
|
||||
MCTextField(
|
||||
label: "Name",
|
||||
value: $monsterName)
|
||||
|
||||
// Editable Text field bound to monster.size
|
||||
MCTextField(
|
||||
label: "Size",
|
||||
value: $monsterSize)
|
||||
|
||||
// Editable Text field bound to monster.type
|
||||
MCTextField(
|
||||
label: "Type",
|
||||
value: $monsterType)
|
||||
|
||||
// Editable Text field bound to monster.subType
|
||||
MCTextField(
|
||||
label: "Subtype",
|
||||
value: $monsterSubtype)
|
||||
|
||||
// Editable Text field bound to monster.alignment
|
||||
MCTextField(
|
||||
label: "Alignment",
|
||||
value: $monsterAlignment)
|
||||
|
||||
// Number with -/+ buttons bound to monster.hitDice
|
||||
MCStepperField(
|
||||
label: "Hit Dice",
|
||||
value: $monsterHitDice)
|
||||
|
||||
// Toggle bound to monster.hasCustomHP?
|
||||
Toggle(
|
||||
"Has Custom HP",
|
||||
isOn:$monsterHasCustomHP)
|
||||
|
||||
// Editable Text field bound to monster.customHpText?
|
||||
MCTextField(
|
||||
label: "Custom HP",
|
||||
value: $monsterCustomHP)
|
||||
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
Section(header: Text("Armor")) {
|
||||
// Armor Type select bound to monster.armorType?
|
||||
// TODO: this should be a select/dropdown
|
||||
MCTextField(
|
||||
label: "Armor Type",
|
||||
value: $monsterArmorType)
|
||||
|
||||
// Toggle bound to monster.hasShield?
|
||||
Toggle(
|
||||
"Has Shield",
|
||||
isOn: $monsterHasShield)
|
||||
|
||||
// Number with -/+ buttons bound to monster.naturalArmorBonus
|
||||
MCStepperField(
|
||||
label: "Natural Armor Bonus",
|
||||
value: $monsterNaturalArmorBonus)
|
||||
|
||||
// Editable Text field bound to monster.customArmorText?
|
||||
MCTextField(
|
||||
label: "Custom Armor",
|
||||
value: $monsterCustomArmor)
|
||||
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
Section(header: Text("Speed")) {
|
||||
// Number bound to monster.baseSpeed
|
||||
MCStepperField(
|
||||
label: "Base",
|
||||
step: 5,
|
||||
suffix: " ft.",
|
||||
value: $monsterBaseSpeed)
|
||||
|
||||
// Number bound to monster.burrowSpeed
|
||||
MCStepperField(
|
||||
label: "Burrow",
|
||||
step: 5,
|
||||
suffix: " ft.",
|
||||
value: $monsterBurrowSpeed)
|
||||
|
||||
// Number bound to monster.climbSpeed
|
||||
MCStepperField(
|
||||
label: "Climb",
|
||||
step: 5,
|
||||
suffix: " ft.",
|
||||
value: $monsterClimbSpeed)
|
||||
|
||||
// Number bound to monster.flySpeed
|
||||
MCStepperField(
|
||||
label: "Fly",
|
||||
step: 5,
|
||||
suffix: " ft.",
|
||||
value: $monsterFlySpeed)
|
||||
|
||||
// Toggle bound to monster.canHover
|
||||
Toggle(
|
||||
"Can Hover",
|
||||
isOn: $monsterCanHover)
|
||||
|
||||
// Number bound to monster.swimSpeed
|
||||
MCStepperField(
|
||||
label: "Swim",
|
||||
step: 5,
|
||||
suffix: " ft.",
|
||||
value: $monsterSwimSpeed)
|
||||
|
||||
// Toggle bound to monster.hasCustomSpeed
|
||||
Toggle(
|
||||
"Has Custom Speed",
|
||||
isOn: $monsterHasCustomSpeed)
|
||||
|
||||
// Editable Text field bound to monster.customSpeedText
|
||||
MCTextField(
|
||||
label: "Custom Speed",
|
||||
value: $monsterCustomSpeed)
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
Section(header: Text("Ability Scores")) {
|
||||
MCStepperField(
|
||||
label: "STR",
|
||||
value: $monsterStrengthScore)
|
||||
MCStepperField(
|
||||
label: "DEX",
|
||||
value: $monsterDexterityScore)
|
||||
MCStepperField(
|
||||
label: "CON",
|
||||
value: $monsterConstitutionScore)
|
||||
MCStepperField(
|
||||
label: "INT",
|
||||
value: $monsterIntelligenceScore)
|
||||
MCStepperField(
|
||||
label: "WIS",
|
||||
value: $monsterWisdomScore)
|
||||
MCStepperField(
|
||||
label: "CHA",
|
||||
value: $monsterCharismaScore)
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
Section(header: Text("Saving Throws")) {
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Strength Advantage",
|
||||
value: $monsterStrengthSavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Strength Proficiency",
|
||||
value: $monsterStrengthSavingThrowProficiency)
|
||||
}
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Dexterity Advantage",
|
||||
value: $monsterDexteritySavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Dexterity Proficiency",
|
||||
value: $monsterDexteritySavingThrowProficiency)
|
||||
}
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Constitution Advantage",
|
||||
value: $monsterConstitutionSavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Constitution Proficiency",
|
||||
value: $monsterConstitutionSavingThrowProficiency)
|
||||
}
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Intelligence Advantage",
|
||||
value: $monsterIntelligenceSavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Intelligence Proficiency",
|
||||
value: $monsterIntelligenceSavingThrowProficiency)
|
||||
}
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Wisdom Advantage",
|
||||
value: $monsterWisdomSavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Wisdom Proficiency",
|
||||
value: $monsterWisdomSavingThrowProficiency)
|
||||
}
|
||||
VStack {
|
||||
MCAdvantagePicker(
|
||||
label: "Charisma Advantage",
|
||||
value: $monsterCharismaSavingThrowAdvantage)
|
||||
|
||||
MCProficiencyPicker(
|
||||
label: "Charisma Proficiency",
|
||||
value: $monsterCharismaSavingThrowProficiency)
|
||||
}
|
||||
}
|
||||
.textCase(nil)
|
||||
}
|
||||
.onAppear(perform: copyMonsterToLocal)
|
||||
.toolbar(content: {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Save", action: saveMonster)
|
||||
}
|
||||
ToolbarItem(placement: ToolbarItemPlacement.cancellationAction) {
|
||||
Button("Cancel", action: cancel)
|
||||
}
|
||||
})
|
||||
.navigationTitle(monster.name ?? "")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
}
|
||||
|
||||
private func dismissView() {
|
||||
self.presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
|
||||
private func saveMonster() {
|
||||
copyLocalToMonster()
|
||||
|
||||
do {
|
||||
try viewContext.save()
|
||||
} catch {
|
||||
// Replace this implementation with code to handle the error appropriately.
|
||||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||
let nsError = error as NSError
|
||||
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
|
||||
}
|
||||
// TODO: save coredata context
|
||||
dismissView()
|
||||
}
|
||||
|
||||
private func cancel() {
|
||||
dismissView()
|
||||
}
|
||||
|
||||
private func copyMonsterToLocal() {
|
||||
monsterName = monster.name ?? ""
|
||||
monsterSize = monster.size ?? ""
|
||||
monsterType = monster.type ?? ""
|
||||
monsterSubtype = monster.subtype ?? ""
|
||||
monsterAlignment = monster.alignment ?? ""
|
||||
monsterHitDice = monster.hitDice
|
||||
monsterHasCustomHP = monster.hasCustomHP
|
||||
monsterCustomHP = monster.customHP ?? ""
|
||||
monsterArmorType = monster.armorType ?? ""
|
||||
monsterHasShield = monster.hasShield
|
||||
monsterNaturalArmorBonus = monster.naturalArmorBonus
|
||||
monsterCustomArmor = monster.customArmor ?? ""
|
||||
monsterBaseSpeed = monster.baseSpeed
|
||||
monsterBurrowSpeed = monster.burrowSpeed
|
||||
monsterClimbSpeed = monster.climbSpeed
|
||||
monsterFlySpeed = monster.flySpeed
|
||||
monsterCanHover = monster.canHover
|
||||
monsterSwimSpeed = monster.swimSpeed
|
||||
monsterHasCustomSpeed = monster.hasCustomSpeed
|
||||
monsterCustomSpeed = monster.customSpeed ?? ""
|
||||
monsterStrengthScore = monster.strengthScore
|
||||
monsterDexterityScore = monster.dexterityScore
|
||||
monsterConstitutionScore = monster.constitutionScore
|
||||
monsterIntelligenceScore = monster.intelligenceScore
|
||||
monsterWisdomScore = monster.wisdomScore
|
||||
monsterCharismaScore = monster.charismaScore
|
||||
monsterStrengthSavingThrowProficiency = ProficiencyType.init(rawValue: monster.strengthSavingThrowProficiency ?? "") ?? .none
|
||||
monsterStrengthSavingThrowAdvantage = AdvantageType(rawValue: monster.strengthSavingThrowAdvantage ?? "") ?? .none
|
||||
monsterDexteritySavingThrowProficiency = ProficiencyType(rawValue: monster.dexteritySavingThrowProficiency ?? "") ?? .none
|
||||
monsterDexteritySavingThrowAdvantage = AdvantageType(rawValue: monster.dexteritySavingThrowAdvantage ?? "") ?? .none
|
||||
monsterConstitutionSavingThrowProficiency = ProficiencyType(rawValue: monster.constitutionSavingThrowProficiency ?? "") ?? .none
|
||||
monsterConstitutionSavingThrowAdvantage = AdvantageType(rawValue: monster.constitutionSavingThrowAdvantage ?? "") ?? .none
|
||||
monsterIntelligenceSavingThrowProficiency = ProficiencyType(rawValue: monster.intelligenceSavingThrowProficiency ?? "") ?? .none
|
||||
monsterIntelligenceSavingThrowAdvantage = AdvantageType(rawValue: monster.intelligenceSavingThrowAdvantage ?? "") ?? .none
|
||||
monsterWisdomSavingThrowProficiency = ProficiencyType(rawValue: monster.wisdomSavingThrowProficiency ?? "") ?? .none
|
||||
monsterWisdomSavingThrowAdvantage = AdvantageType(rawValue: monster.wisdomSavingThrowAdvantage ?? "") ?? .none
|
||||
monsterCharismaSavingThrowProficiency = ProficiencyType(rawValue: monster.charismaSavingThrowProficiency ?? "") ?? .none
|
||||
monsterCharismaSavingThrowAdvantage = AdvantageType(rawValue: monster.charismaSavingThrowAdvantage ?? "") ?? .none
|
||||
}
|
||||
|
||||
private func copyLocalToMonster() {
|
||||
monster.name = monsterName
|
||||
monster.size = monsterSize
|
||||
monster.type = monsterType
|
||||
monster.subtype = monsterSubtype
|
||||
monster.alignment = monsterAlignment
|
||||
monster.hitDice = monsterHitDice
|
||||
monster.hasCustomHP = monsterHasCustomHP
|
||||
monster.customHP = monsterCustomHP
|
||||
monster.armorType = monsterArmorType
|
||||
monster.hasShield = monsterHasShield
|
||||
monster.naturalArmorBonus = monsterNaturalArmorBonus
|
||||
monster.customArmor = monsterCustomArmor
|
||||
monster.baseSpeed = monsterBaseSpeed
|
||||
monster.burrowSpeed = monsterBurrowSpeed
|
||||
monster.climbSpeed = monsterClimbSpeed
|
||||
monster.flySpeed = monsterFlySpeed
|
||||
monster.canHover = monsterCanHover
|
||||
monster.swimSpeed = monsterSwimSpeed
|
||||
monster.hasCustomSpeed = monsterHasCustomSpeed
|
||||
monster.customSpeed = monsterCustomSpeed
|
||||
monster.strengthScore = monsterStrengthScore
|
||||
monster.dexterityScore = monsterDexterityScore
|
||||
monster.constitutionScore = monsterConstitutionScore
|
||||
monster.intelligenceScore = monsterIntelligenceScore
|
||||
monster.wisdomScore = monsterWisdomScore
|
||||
monster.charismaScore = monsterCharismaScore
|
||||
monster.strengthSavingThrowProficiency = monsterStrengthSavingThrowProficiency.rawValue
|
||||
monster.strengthSavingThrowAdvantage = monsterStrengthSavingThrowAdvantage.rawValue
|
||||
monster.dexteritySavingThrowProficiency = monsterDexteritySavingThrowProficiency.rawValue
|
||||
monster.dexteritySavingThrowAdvantage = monsterDexteritySavingThrowAdvantage.rawValue
|
||||
monster.constitutionSavingThrowProficiency = monsterConstitutionSavingThrowProficiency.rawValue
|
||||
monster.constitutionSavingThrowAdvantage = monsterConstitutionSavingThrowAdvantage.rawValue
|
||||
monster.intelligenceSavingThrowProficiency = monsterIntelligenceSavingThrowProficiency.rawValue
|
||||
monster.intelligenceSavingThrowAdvantage = monsterIntelligenceSavingThrowAdvantage.rawValue
|
||||
monster.wisdomSavingThrowProficiency = monsterWisdomSavingThrowProficiency.rawValue
|
||||
monster.wisdomSavingThrowAdvantage = monsterWisdomSavingThrowAdvantage.rawValue
|
||||
monster.charismaSavingThrowProficiency = monsterCharismaSavingThrowProficiency.rawValue
|
||||
monster.charismaSavingThrowAdvantage = monsterCharismaSavingThrowAdvantage.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
struct EditMonster_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let monster = Monster.init(context: context)
|
||||
|
||||
monster.name = "Steve"
|
||||
monster.size = "Medium"
|
||||
monster.type = "humanoid"
|
||||
monster.subtype = "human"
|
||||
monster.alignment = "LG"
|
||||
monster.hitDice = 6
|
||||
monster.hasCustomHP = true
|
||||
monster.customHP = "12 (1d10)+2"
|
||||
monster.baseSpeed = 5
|
||||
monster.burrowSpeed = 10
|
||||
monster.climbSpeed = 15
|
||||
monster.flySpeed = 20
|
||||
monster.swimSpeed = 25
|
||||
monster.canHover = true
|
||||
monster.hasCustomSpeed = false
|
||||
monster.customSpeed = "walk: 5 ft."
|
||||
monster.strengthScore = 8
|
||||
monster.dexterityScore = 10
|
||||
monster.constitutionScore = 12
|
||||
monster.intelligenceScore = 14
|
||||
monster.wisdomScore = 16
|
||||
monster.charismaScore = 18
|
||||
monster.strengthSavingThrowAdvantage = AdvantageType.none.rawValue
|
||||
monster.strengthSavingThrowProficiency = ProficiencyType.none.rawValue
|
||||
monster.dexteritySavingThrowAdvantage = AdvantageType.advantage.rawValue
|
||||
monster.dexteritySavingThrowProficiency = ProficiencyType.proficient.rawValue
|
||||
monster.constitutionSavingThrowAdvantage = AdvantageType.disadvantage.rawValue
|
||||
monster.constitutionSavingThrowProficiency = ProficiencyType.expertise.rawValue
|
||||
monster.intelligenceSavingThrowAdvantage = AdvantageType.none.rawValue
|
||||
monster.intelligenceSavingThrowProficiency = ProficiencyType.expertise.rawValue
|
||||
monster.wisdomSavingThrowAdvantage = AdvantageType.advantage.rawValue
|
||||
monster.wisdomSavingThrowProficiency = ProficiencyType.proficient.rawValue
|
||||
monster.charismaSavingThrowAdvantage = AdvantageType.disadvantage.rawValue
|
||||
monster.charismaSavingThrowProficiency = ProficiencyType.none.rawValue
|
||||
|
||||
return EditMonster(monster: monster).environment(\.managedObjectContext, context)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user