Adds Saving Throws to the data model and monster editor.

This commit is contained in:
2020-10-03 22:31:47 -07:00
parent 23b840f3ff
commit 3c3ed3c94b
10 changed files with 634 additions and 151 deletions

View File

@@ -9,6 +9,7 @@
#import "EditMonsterViewController.h"
#import "MCBooleanFieldTableViewCell.h"
#import "MCIntegerFieldTableViewCell.h"
#import "MCRadioFieldTableViewCell.h"
#import "MCSelectFieldTableViewCell.h"
#import "MCShortStringFieldTableViewCell.h"
#import "AppDelegate.h"
@@ -23,6 +24,7 @@ const int kSectionIndexBasicInfo = 0;
const int kSectionIndexArmor = 1;
const int kSectionIndexSpeed = 2;
const int kSectionIndexAbilityScores = 3;
const int kSectionIndexSavingThrows = 4;
const int kBasicInfoSectionRowIndexName = 0;
const int kBasicInfoSectionRowIndexSize = 1;
@@ -54,9 +56,63 @@ const int kAbilityScoreSectionRowIndexIntelligence = 3;
const int kAbilityScoreSectionRowIndexWisdom = 4;
const int kAbilityScoreSectionRowIndexCharisma = 5;
const int kSavingThrowsSectionRowIndexStrengthProficiency = 0;
const int kSavingThrowsSectionRowIndexStrengthAdvantage = 1;
const int kSavingThrowsSectionRowIndexDexterityProficiency = 2;
const int kSavingThrowsSectionRowIndexDexterityAdvantage = 3;
const int kSavingThrowsSectionRowIndexConstitutionProficiency = 4;
const int kSavingThrowsSectionRowIndexConstitutionAdvantage = 5;
const int kSavingThrowsSectionRowIndexIntelligenceProficiency = 6;
const int kSavingThrowsSectionRowIndexIntelligenceAdvantage = 7;
const int kSavingThrowsSectionRowIndexWisdomProficiency = 8;
const int kSavingThrowsSectionRowIndexWisdomAdvantage = 9;
const int kSavingThrowsSectionRowIndexCharismaProficiency = 10;
const int kSavingThrowsSectionRowIndexCharismaAdvantage = 11;
NSString *const kIdentifierName = @"monster.name";
NSString *const kIdentifierSize = @"monster.size";
NSString *const kIdentifierType = @"monster.type";
NSString *const kIdentifierSubtype = @"monster.subtype";
NSString *const kIdentifierAlignment = @"monster.alignment";
NSString *const kIdentifierCustomHP = @"monster.customHPText";
NSString *const kIdentifierCustomSpeed = @"monster.customSpeed";
NSString *const kIdentifierCustomArmor = @"monster.customArmor";
NSString *const kIdentifierStrengthScore = @"monster.strengthScore";
NSString *const kIdentiferDexterityScore = @"monster.dexterityScore";
NSString *const kIdentifierConstitutionScore = @"monster.constitutionScore";
NSString *const kIdentifierIntelligenceScore = @"monster.intelligenceScore";
NSString *const kIdentifierWisdomScore = @"monster.wisdomScore";
NSString *const kIdentifierCharismaScore = @"monster.charismaScore";
NSString *const kIdentifierHitDice = @"monster.hitDice";
NSString *const kIdentifierBaseSpeed = @"monster.baseSpeed";
NSString *const kIdentifierBurrowSpeed = @"monster.burrowSpeed";
NSString *const kIdentifierClimbSpeed = @"monster.climbSpeed";
NSString *const kIdentifierFlySpeed = @"monster.flySpeed";
NSString *const kIdentifierSwimSpeed = @"monster.swimSpeed";
NSString *const kIdentifierNaturalArmorBonus = @"monster.naturalArmorBonus";
NSString *const kIdentifierHasCustomHP = @"monster.customHP";
NSString *const kIdentifierCanHover = @"monster.canHover";
NSString *const kIdentifierHasCustomSpeed = @"monster.hasCustomSpeed";
NSString *const kIdentifierHasShield = @"monster.hasShield";
NSString *const kIdentifierArmorType = @"monster.armorType";
NSString *const kIdentifierStrengthSavingThrowAdvantage = @"monster.savingThrows.strength.advantage";
NSString *const kIdentifierStrengthSavingThrowProficiency = @"monster.savingThrows.strength.proficiency";
NSString *const kIdentifierDexteritySavingThrowAdvantage = @"monster.savingThrows.dexterity.advantage";
NSString *const kIdentifierDexteritySavingThrowProficiency = @"monster.savingThrows.dexterity.proficiency";
NSString *const kIdentifierConstitutionSavingThrowAdvantage = @"monster.savingThrows.constitution.advantage";
NSString *const kIdentifierConstitutionSavingThrowProficiency = @"monster.savingThrows.constitution.proficiency";
NSString *const kIdentifierIntelligenceSavingThrowAdvantage = @"monster.savingThrows.intelligence.advantage";
NSString *const kIdentifierIntelligenceSavingThrowProficiency = @"monster.savingThrows.intelligence.proficiency";
NSString *const kIdentifierWisdomSavingThrowAdvantage = @"monster.savingThrows.wisdom.advantage";
NSString *const kIdentifierWisdomSavingThrowProficiency = @"monster.savingThrows.wisdom.proficiency";
NSString *const kIdentifierCharismaSavingThrowAdvantage = @"monster.savingThrows.charisma.advantage";
NSString *const kIdentifierCharismaSavingThrowProficiency = @"monster.savingThrows.charisma.proficiency";
@implementation EditMonsterViewController {
NSManagedObjectContext *_context;
NSArray<MCChoice*>* _armorTypes;
NSArray<MCChoice*>* _proficiencyTypes;
NSArray<MCChoice*>* _advantageTypes;
}
- (void)viewDidLoad {
@@ -98,6 +154,22 @@ const int kAbilityScoreSectionRowIndexCharisma = 5;
[MCChoice choiceWithLabel:NSLocalizedString(@"Other", @"")
andValue:kArmorNameOther],
nil];
_proficiencyTypes = [NSArray arrayWithObjects:
[MCChoice choiceWithLabel:NSLocalizedString(@"None", @"")
andValue:kProficiencyTypeNone],
[MCChoice choiceWithLabel:NSLocalizedString(@"Proficient", @"")
andValue:kProficiencyTypeProficient],
[MCChoice choiceWithLabel:NSLocalizedString(@"Expertise", @"")
andValue:kProficiencyTypeExpertise],
nil];
_advantageTypes = [NSArray arrayWithObjects:
[MCChoice choiceWithLabel:NSLocalizedString(@"None", @"")
andValue:kAdvantageTypeNone],
[MCChoice choiceWithLabel:NSLocalizedString(@"Advantage", @"")
andValue:kAdvantageTypeAdvantage],
[MCChoice choiceWithLabel:NSLocalizedString(@"Disadvantage", @"")
andValue:kAdvantageTypeDisadvantage],
nil];
self.monsterTableView.allowsSelection = NO;
self.monsterTableView.allowsSelectionDuringEditing = NO;
@@ -188,6 +260,24 @@ const int kAbilityScoreSectionRowIndexCharisma = 5;
return cell;
}
- (MCRadioFieldTableViewCell*) makeRadioCellFromTableView:(UITableView*)tableView
withIdentifier:(NSString*)identifier
label:(NSString*)label
initialValue:(NSObject*)initialValue
andChoices:(NSArray*)choices {
MCRadioFieldTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MCRadioField"];
if (!cell || ![cell isKindOfClass:[MCRadioFieldTableViewCell class]]) {
return nil;
}
cell.delegate = self;
cell.identifier = identifier;
cell.label = label;
// TODO: possibly swap these two
cell.selectedValue = initialValue;
cell.choices = choices;
return cell;
}
#pragma mark - Navigation
@@ -222,6 +312,8 @@ const int kAbilityScoreSectionRowIndexCharisma = 5;
return 8;
case kSectionIndexAbilityScores:
return 6;
case kSectionIndexSavingThrows:
return 12; // 12
default:
return 0;
}
@@ -229,7 +321,7 @@ const int kAbilityScoreSectionRowIndexCharisma = 5;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
return 5;
}
- (NSString *)tableView:(UITableView *)tableView
@@ -243,6 +335,8 @@ titleForHeaderInSection:(NSInteger)section {
return NSLocalizedString(@"Speed", @"Section title");
case kSectionIndexAbilityScores:
return NSLocalizedString(@"Ability Scores", @"Section title");
case kSectionIndexSavingThrows:
return NSLocalizedString(@"Saving Throws", @"Section title");
default:
return nil;
}
@@ -257,49 +351,49 @@ titleForHeaderInSection:(NSInteger)section {
switch (indexPath.row) {
case kBasicInfoSectionRowIndexName:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.name"
withIdentifier:kIdentifierName
label:NSLocalizedString(@"Name", @"Placeholder text for the name of a monster or NPC.")
andInitialValue:self.editingMonster.name];
break;
case kBasicInfoSectionRowIndexSize:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.size"
withIdentifier:kIdentifierSize
label:NSLocalizedString(@"Size", @"Placehodler text for the size of a monster or NPC.")
andInitialValue:self.editingMonster.size];
break;
case kBasicInfoSectionRowIndexType:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.type"
withIdentifier:kIdentifierType
label:NSLocalizedString(@"Type", @"Placehodler text for the type of a monster or NPC.")
andInitialValue:self.editingMonster.type];
break;
case kBasicInfoSectionRowIndexSubtype:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.subtype"
withIdentifier:kIdentifierSubtype
label:NSLocalizedString(@"Subtype", @"Placeholder text for the subtype of a monster or NPC.")
andInitialValue:self.editingMonster.subtype];
break;
case kBasicInfoSectionRowIndexAlignment:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.alignment"
withIdentifier:kIdentifierAlignment
label: NSLocalizedString(@"Alignment", @"Placeholder text for the alignment of a monster or NPC.")
andInitialValue:self.editingMonster.alignment];
break;
case kBasicInfoSectionRowIndexHitDice:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.hitDice"
withIdentifier:kIdentifierHitDice
label:NSLocalizedString(@"Hit Dice", @"")
andInitialValue:self.editingMonster.hitDice];
break;
case kBasicInfoSectionRowIndexCustomHP:
newCell = [self makeBooleanCellFromTableView:self.monsterTableView
withIdentifier:@"monster.customHP"
withIdentifier:kIdentifierHasCustomHP
label:NSLocalizedString(@"Custom HP", @"")
andInitialValue:self.editingMonster.customHP];
break;
case kBasicInfoSectionRowIndexCustomHPText:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.customHPText"
withIdentifier:kIdentifierCustomHP
label:NSLocalizedString(@"Custom HP Text", @"")
andInitialValue:self.editingMonster.hpText];
break;
@@ -309,26 +403,26 @@ titleForHeaderInSection:(NSInteger)section {
switch (indexPath.row) {
case kArmorSectionRowIndexArmorType:
newCell = [self makeSelectCellFromTableView:self.monsterTableView
withIdentifier:@"monster.armorType"
withIdentifier:kIdentifierArmorType
label:NSLocalizedString(@"Type", @"")
initialValue:self.editingMonster.armorType
andChoices:_armorTypes];
break;
case kArmorSectionRowIndexHasShield:
newCell = [self makeBooleanCellFromTableView:self.monsterTableView
withIdentifier:@"monster.hasShield"
withIdentifier:kIdentifierHasShield
label:NSLocalizedString(@"Shield", @"")
andInitialValue:self.editingMonster.hasShield];
break;
case kArmorSectionRowIndexCustomArmor:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.customArmor"
withIdentifier:kIdentifierCustomArmor
label:NSLocalizedString(@"Custom Armor", @"")
andInitialValue:self.editingMonster.customArmor];
break;
case kArmorSectionRowIndexNaturalArmorBonus:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.naturalArmorBonus"
withIdentifier:kIdentifierNaturalArmorBonus
label:NSLocalizedString(@"Natural Armor Bonus", @"")
andInitialValue:self.editingMonster.naturalArmorBonus];
break;
@@ -338,49 +432,49 @@ titleForHeaderInSection:(NSInteger)section {
switch (indexPath.row) {
case kSpeedSectionRowIndexBaseSpeed:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.baseSpeed"
withIdentifier:kIdentifierBaseSpeed
label:NSLocalizedString(@"Base", @"")
andInitialValue:self.editingMonster.baseSpeed];
break;
case kSpeedSectionRowIndexBurrowSpeed:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.burrowSpeed"
withIdentifier:kIdentifierBurrowSpeed
label:NSLocalizedString(@"Burrow", @"")
andInitialValue:self.editingMonster.burrowSpeed];
break;
case kSpeedSectionRowIndexClimbSpeed:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.climbSpeed"
withIdentifier:kIdentifierClimbSpeed
label:NSLocalizedString(@"Climb", @"")
andInitialValue:self.editingMonster.climbSpeed];
break;
case kSpeedSectionRowIndexFlySpeed:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.flySpeed"
withIdentifier:kIdentifierFlySpeed
label:NSLocalizedString(@"Fly", @"")
andInitialValue:self.editingMonster.flySpeed];
break;
case kSpeedSectionRowIndexCanHover:
newCell = [self makeBooleanCellFromTableView:self.monsterTableView
withIdentifier:@"monster.canHover"
withIdentifier:kIdentifierCanHover
label:NSLocalizedString(@"Hover", @"")
andInitialValue:self.editingMonster.canHover];
break;
case kSpeedSectionRowIndexSwimSpeed:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.swimSpeed"
withIdentifier:kIdentifierSwimSpeed
label:NSLocalizedString(@"Swim", @"")
andInitialValue:self.editingMonster.swimSpeed];
break;
case kSpeedSectionRowIndexHasCustomSpeed:
newCell = [self makeBooleanCellFromTableView:self.monsterTableView
withIdentifier:@"monster.hasCustomSpeed"
withIdentifier:kIdentifierHasCustomSpeed
label:NSLocalizedString(@"Custom Speed", @"")
andInitialValue:self.editingMonster.hasCustomSpeed];
break;
case kSpeedSectionRowIndexCustomSpeed:
newCell = [self makeShortStringCellFromTableView:self.monsterTableView
withIdentifier:@"monster.customSpeed"
withIdentifier:kIdentifierCustomSpeed
label:NSLocalizedString(@"Custom Speed", @"")
andInitialValue:self.editingMonster.customSpeed];
break;
@@ -390,43 +484,131 @@ titleForHeaderInSection:(NSInteger)section {
switch (indexPath.row) {
case kAbilityScoreSectionRowIndexStrength:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.strengthScore"
withIdentifier:kIdentifierStrengthScore
label:NSLocalizedString(@"STR", @"Placeholder abbreviation for the strength score of a monster or NPC.")
andInitialValue:self.editingMonster.strengthScore];
break;
case kAbilityScoreSectionRowIndexDexterity:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.dexterityScore"
withIdentifier:kIdentiferDexterityScore
label:NSLocalizedString(@"DEX", @"Placeholder abbreviation for the dexterity score of a monster or NPC.")
andInitialValue:self.editingMonster.dexterityScore];
break;
case kAbilityScoreSectionRowIndexConstitution:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.constitutionScore"
withIdentifier:kIdentifierConstitutionScore
label:NSLocalizedString(@"CON", @"Placeholder abbreviation for the constitution score of a monster or NPC.")
andInitialValue:self.editingMonster.constitutionScore];
break;
case kAbilityScoreSectionRowIndexIntelligence:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.intelligenceScore"
withIdentifier:kIdentifierIntelligenceScore
label:NSLocalizedString(@"INT", @"Placeholder abbreviation for the intelligence score of a monster or NPC.")
andInitialValue:self.editingMonster.intelligenceScore];
break;
case kAbilityScoreSectionRowIndexWisdom:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.wisdomScore"
withIdentifier:kIdentifierWisdomScore
label:NSLocalizedString(@"WIS", @"Placeholder abbreviation for the wisdom score of a monster or NPC.")
andInitialValue:self.editingMonster.wisdomScore];
break;
case kAbilityScoreSectionRowIndexCharisma:
newCell = [self makeIntegerCellFromTableView:self.monsterTableView
withIdentifier:@"monster.charismaScore"
withIdentifier:kIdentifierCharismaScore
label:NSLocalizedString(@"CHA", @"Placeholder abbreviation for the charisma score of a monster or NPC.")
andInitialValue:self.editingMonster.charismaScore];
break;
}
break;
case kSectionIndexSavingThrows:
switch (indexPath.row) {
case kSavingThrowsSectionRowIndexStrengthProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierStrengthSavingThrowProficiency
label:NSLocalizedString(@"Strength Proficiency", @"")
initialValue:self.editingMonster.strengthSavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexStrengthAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierStrengthSavingThrowAdvantage
label:NSLocalizedString(@"Strength Advantage", @"")
initialValue:self.editingMonster.strengthSavingThrowAdvantage
andChoices:_advantageTypes];
break;
case kSavingThrowsSectionRowIndexDexterityProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierDexteritySavingThrowProficiency
label:NSLocalizedString(@"Dexterity Proficiency", @"")
initialValue:self.editingMonster.dexteritySavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexDexterityAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierDexteritySavingThrowAdvantage
label:NSLocalizedString(@"Dexterity Advantage", @"")
initialValue:self.editingMonster.dexteritySavingThrowAdvantage
andChoices:_advantageTypes];
break;
case kSavingThrowsSectionRowIndexConstitutionProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierConstitutionSavingThrowProficiency
label:NSLocalizedString(@"Constitution Proficiency", @"")
initialValue:self.editingMonster.constitutionSavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexConstitutionAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierConstitutionSavingThrowAdvantage
label:NSLocalizedString(@"Constitution Advantage", @"")
initialValue:self.editingMonster.constitutionSavingThrowAdvantage
andChoices:_advantageTypes];
break;
case kSavingThrowsSectionRowIndexIntelligenceProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierIntelligenceSavingThrowProficiency
label:NSLocalizedString(@"Intelligence Proficiency", @"")
initialValue:self.editingMonster.intelligenceSavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexIntelligenceAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierIntelligenceSavingThrowAdvantage
label:NSLocalizedString(@"Intelligence Advantage", @"")
initialValue:self.editingMonster.intelligenceSavingThrowAdvantage
andChoices:_advantageTypes];
break;
case kSavingThrowsSectionRowIndexWisdomProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierWisdomSavingThrowProficiency
label:NSLocalizedString(@"Wisdom Proficiency", @"")
initialValue:self.editingMonster.wisdomSavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexWisdomAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierWisdomSavingThrowAdvantage
label:NSLocalizedString(@"Wisdom Advantage", @"")
initialValue:self.editingMonster.wisdomSavingThrowAdvantage
andChoices:_advantageTypes];
break;
case kSavingThrowsSectionRowIndexCharismaProficiency:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierCharismaSavingThrowProficiency
label:NSLocalizedString(@"Charisma Proficiency", @"")
initialValue:self.editingMonster.charismaSavingThrowProficiency
andChoices:_proficiencyTypes];
break;
case kSavingThrowsSectionRowIndexCharismaAdvantage:
newCell = [self makeRadioCellFromTableView:self.monsterTableView
withIdentifier:kIdentifierCharismaSavingThrowAdvantage
label:NSLocalizedString(@"Charisma Advantage", @"")
initialValue:self.editingMonster.charismaSavingThrowAdvantage
andChoices:_advantageTypes];
break;
}
break;
}
if (!newCell) {
@@ -441,69 +623,97 @@ titleForHeaderInSection:(NSInteger)section {
- (void)editableValueDidChange:(NSObject*)value forIdentifier:(NSString*)identifier andType:(NSString*)type {
if ([kMCFieldValueTypeString isEqualToString:type]) {
if ([@"monster.name" isEqualToString:identifier]) {
if ([kIdentifierName isEqualToString:identifier]) {
self.editingMonster.name = (NSString*)value;
} else if ([@"monster.size" isEqualToString:identifier]) {
} else if ([kIdentifierSize isEqualToString:identifier]) {
self.editingMonster.size = (NSString*)value;
} else if ([@"monster.type" isEqualToString:identifier]) {
} else if ([kIdentifierType isEqualToString:identifier]) {
self.editingMonster.type = (NSString*)value;
} else if ([@"monster.subtype" isEqualToString:identifier]) {
} else if ([kIdentifierSubtype isEqualToString:identifier]) {
self.editingMonster.subtype = (NSString*)value;
} else if ([@"monster.alignment" isEqualToString:identifier]) {
} else if ([kIdentifierAlignment isEqualToString:identifier]) {
self.editingMonster.alignment = (NSString*)value;
} else if ([@"monster.customHPText" isEqualToString:identifier]) {
} else if ([kIdentifierCustomHP isEqualToString:identifier]) {
self.editingMonster.hpText = (NSString*)value;
} else if ([@"monster.customSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierCustomSpeed isEqualToString:identifier]) {
self.editingMonster.customSpeed = (NSString*)value;
} else if ([@"monster.customArmor" isEqualToString:identifier]) {
} else if ([kIdentifierCustomArmor isEqualToString:identifier]) {
self.editingMonster.customArmor = (NSString*)value;
}
}
if ([kMCFieldValueTypeInteger isEqualToString:type]) {
if ([@"monster.strengthScore" isEqualToString:identifier]) {
if ([kIdentifierStrengthScore isEqualToString:identifier]) {
self.editingMonster.strengthScore = [(NSNumber*)value intValue];
} else if ([@"monster.dexterityScore" isEqualToString:identifier]) {
} else if ([kIdentiferDexterityScore isEqualToString:identifier]) {
self.editingMonster.dexterityScore = [(NSNumber*)value intValue];
} else if ([@"monster.constitutionScore" isEqualToString:identifier]) {
} else if ([kIdentifierConstitutionScore isEqualToString:identifier]) {
self.editingMonster.constitutionScore = [(NSNumber*)value intValue];
} else if ([@"monster.intelligenceScore" isEqualToString:identifier]) {
} else if ([kIdentifierIntelligenceScore isEqualToString:identifier]) {
self.editingMonster.intelligenceScore = [(NSNumber*)value intValue];
} else if ([@"monster.wisdomScore" isEqualToString:identifier]) {
} else if ([kIdentifierWisdomScore isEqualToString:identifier]) {
self.editingMonster.wisdomScore = [(NSNumber*)value intValue];
} else if ([@"monster.charismaScore" isEqualToString:identifier]) {
} else if ([kIdentifierCharismaScore isEqualToString:identifier]) {
self.editingMonster.charismaScore = [(NSNumber*)value intValue];
} else if ([@"monster.hitDice" isEqualToString:identifier]) {
} else if ([kIdentifierHitDice isEqualToString:identifier]) {
self.editingMonster.hitDice = [(NSNumber*)value intValue];
} else if ([@"monster.baseSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierBaseSpeed isEqualToString:identifier]) {
self.editingMonster.baseSpeed = [(NSNumber*)value intValue];
} else if ([@"monster.burrowSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierBurrowSpeed isEqualToString:identifier]) {
self.editingMonster.burrowSpeed = [(NSNumber*)value intValue];
} else if ([@"monster.climbSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierClimbSpeed isEqualToString:identifier]) {
self.editingMonster.climbSpeed = [(NSNumber*)value intValue];
} else if ([@"monster.flySpeed" isEqualToString:identifier]) {
} else if ([kIdentifierFlySpeed isEqualToString:identifier]) {
self.editingMonster.flySpeed = [(NSNumber*)value intValue];
} else if ([@"monster.swimSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierSwimSpeed isEqualToString:identifier]) {
self.editingMonster.swimSpeed = [(NSNumber*)value intValue];
} else if ([@"monster.naturalArmorBonus" isEqualToString:identifier]) {
} else if ([kIdentifierNaturalArmorBonus isEqualToString:identifier]) {
self.editingMonster.naturalArmorBonus = [(NSNumber*)value intValue];
}
}
if ([kMCFieldValueTypeBoolean isEqualToString:type]) {
if ([@"monster.customHP" isEqualToString:identifier]) {
if ([kIdentifierHasCustomHP isEqualToString:identifier]) {
self.editingMonster.customHP = [(NSNumber*)value boolValue];
} else if ([@"monster.canHover" isEqualToString:identifier]) {
} else if ([kIdentifierCanHover isEqualToString:identifier]) {
self.editingMonster.canHover = [(NSNumber*)value boolValue];
} else if ([@"monster.hasCustomSpeed" isEqualToString:identifier]) {
} else if ([kIdentifierHasCustomSpeed isEqualToString:identifier]) {
self.editingMonster.hasCustomSpeed = [(NSNumber*)value boolValue];
} else if ([@"monster.hasShield" isEqualToString:identifier]) {
} else if ([kIdentifierHasShield isEqualToString:identifier]) {
self.editingMonster.hasShield = [(NSNumber*)value boolValue];
}
}
if ([kMCFieldValueTypeChoice isEqualToString:type]) {
if ([@"monster.armorType" isEqualToString:identifier]) {
if ([kIdentifierArmorType isEqualToString:identifier]) {
self.editingMonster.armorType = (NSString*)value;
} else if ([kIdentifierStrengthSavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.strengthSavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierStrengthSavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.strengthSavingThrowProficiency = (NSString*)value;
} else if ([kIdentifierDexteritySavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.dexteritySavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierDexteritySavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.dexteritySavingThrowProficiency = (NSString*)value;
} else if ([kIdentifierConstitutionSavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.constitutionSavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierConstitutionSavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.constitutionSavingThrowProficiency = (NSString*)value;
} else if ([kIdentifierIntelligenceSavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.intelligenceSavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierIntelligenceSavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.intelligenceSavingThrowProficiency = (NSString*)value;
} else if ([kIdentifierWisdomSavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.wisdomSavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierWisdomSavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.wisdomSavingThrowProficiency = (NSString*)value;
} else if ([kIdentifierCharismaSavingThrowAdvantage isEqualToString:identifier]) {
self.editingMonster.charismaSavingThrowAdvantage = (NSString*)value;
} else if ([kIdentifierCharismaSavingThrowProficiency isEqualToString:identifier]) {
self.editingMonster.charismaSavingThrowProficiency = (NSString*)value;
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
@end

View File

@@ -0,0 +1,29 @@
//
// MCRadioFieldTableViewCell.h
// MonsterCards
//
// Created by Tom Hicks on 9/26/20.
// Copyright © 2020 Tom Hicks. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MCFormFieldDelegate.h"
#import "MCChoice.h"
NS_ASSUME_NONNULL_BEGIN
@interface MCRadioFieldTableViewCell : UITableViewCell
@property NSString* identifier;
@property NSString* label;
@property NSObject* selectedValue;
@property NSArray<MCChoice*>* choices;
@property (weak, nonatomic) id<MCFormFieldDelegate> delegate;
@property (weak, nonatomic) IBOutlet UILabel *labelView;
@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,131 @@
//
// MCRadioFieldTableViewCell.m
// MonsterCards
//
// Created by Tom Hicks on 9/26/20.
// Copyright © 2020 Tom Hicks. All rights reserved.
//
#import "MCRadioFieldTableViewCell.h"
@implementation MCRadioFieldTableViewCell {
MCChoice* _selectedChoice;
}
-(MCChoice*)findChoiceWithValue:(NSObject*)value
inArray:(NSArray*)array {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id element, NSDictionary *bindings) {
if (![element isKindOfClass:[MCChoice class]]) {
return NO;
}
MCChoice *choice = (MCChoice*)element;
return [choice.value isEqual:value];
}];
NSArray<MCChoice*> *matchingChoices = [array filteredArrayUsingPredicate:predicate];
MCChoice *foundChoice = matchingChoices.count > 0 ? matchingChoices.firstObject : nil;
return foundChoice;
}
-(void)notifyChangedValue {
NSUInteger selectedIndex = [_choices indexOfObject:_selectedChoice];
[self.segmentedControl setSelectedSegmentIndex:selectedIndex];
if (_delegate) {
[_delegate editableValueDidChange:_selectedValue
forIdentifier:_identifier
andType:kMCFieldValueTypeChoice];
}
}
-(void)updateSegments {
if (_segmentedControl) {
[_segmentedControl removeAllSegments];
int index = 0;
for (MCChoice *choice in _choices) {
[_segmentedControl insertSegmentWithTitle:choice.label atIndex:index animated:NO];
index++;
}
_segmentedControl.selectedSegmentIndex = [_choices indexOfObject:_selectedChoice];
}
}
@synthesize choices = _choices;
-(void)setChoices:(NSArray<MCChoice*>*)choices {
MCChoice *foundChoice = [self findChoiceWithValue:_selectedValue
inArray:choices];
if ([_choices isEqualToArray:choices]) {
// Choices are equivalent so selected value. Pointer may have changed but content hasn't.
_selectedChoice = foundChoice;
} else if (foundChoice) {
// Choices are different but selected value is in the new choices. Pointer may have changed but content hasn't.
_selectedChoice = foundChoice;
} else {
// Choices are different and selected value is not in the new choices. Select the first choice or nil if there are none.
_selectedChoice = [choices firstObject];
}
_choices = choices;
if (_selectedValue != foundChoice.value) {
self.selectedValue = foundChoice.value;
}
[self updateSegments];
}
-(NSArray<MCChoice*>*)choices {
return _choices;
}
@synthesize label = _label;
-(void)setLabel:(NSString*)label {
if (![_label isEqualToString:label]) {
_label = label;
}
if (_labelView && ![_labelView.text isEqualToString:label]) {
_labelView.text = label;
}
}
-(NSString*)label {
return _label;
}
@synthesize selectedValue = _selectedValue;
-(void)setSelectedValue:(NSObject*)value {
NSObject *newValue = nil;
MCChoice *foundChoice = [self findChoiceWithValue:value inArray:_choices];
if (!_choices) {
newValue = value;
} else if (!foundChoice) {
newValue = nil;
} else {
newValue = foundChoice.value;
}
_selectedChoice = foundChoice;
if (_selectedValue != newValue) {
_selectedValue = newValue;
[self notifyChangedValue];
}
}
-(NSObject*)selectedValue {
return _selectedValue;
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)selectedSegmentChanged:(id)sender {
NSInteger selectedIndex = _segmentedControl.selectedSegmentIndex;
MCChoice *newChoice = [_choices objectAtIndex:selectedIndex];
_selectedChoice = newChoice;
_selectedValue = _selectedChoice.value;
[self notifyChangedValue];
}
@end

View File

@@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (weak, nonatomic) id<MCFormFieldDelegate> delegate;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UILabel *labelView;
@property (nonatomic) UIPickerView *pickerView;
@end

View File

@@ -12,32 +12,63 @@
MCChoice* _selectedChoice;
}
-(MCChoice*)findChoiceWithValue:(NSObject*)value
inArray:(NSArray*)array {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id element, NSDictionary *bindings) {
if (![element isKindOfClass:[MCChoice class]]) {
return NO;
}
MCChoice *choice = (MCChoice*)element;
return [choice.value isEqual:value];
}];
NSArray<MCChoice*> *matchingChoices = [array filteredArrayUsingPredicate:predicate];
MCChoice *foundChoice = matchingChoices.count > 0 ? matchingChoices.firstObject : nil;
return foundChoice;
}
-(void)notifyChangedValue {
[self updateView];
if (_delegate) {
[_delegate editableValueDidChange:_selectedValue
forIdentifier:_identifier
andType:kMCFieldValueTypeChoice];
}
}
-(void)updateView {
self.textField.text = _selectedChoice.label;
NSInteger selectedRow = [_choices indexOfObject:_selectedChoice];
[self.pickerView selectRow:selectedRow inComponent:0 animated:YES];
}
@synthesize choices = _choices;
-(void)setChoices:(NSArray<MCChoice*>*)choices {
// TODO: only do this if choices is different
// TODO: update selectedValue and selectedIndex
MCChoice *foundChoice = [self findChoiceWithValue:_selectedValue
inArray:choices];
if ([_choices isEqualToArray:choices]) {
// Choices are equivalent so selected value. Pointer may have changed but content hasn't.
_selectedChoice = foundChoice;
} else if (foundChoice) {
// Choices are different but selected value is in the new choices. Pointer may have changed but content hasn't.
_selectedChoice = foundChoice;
} else {
// Choices are different and selected value is not in the new choices. Select the first choice or nil if there are none.
_selectedChoice = [choices firstObject];
}
_choices = choices;
if (![_choices isEqualToArray:choices]) {
self.selectedValue = _selectedValue;
} else if (choices) {
self.selectedValue = [choices firstObject].value;
if (_selectedValue != foundChoice.value) {
self.selectedValue = foundChoice.value;
}
[self updateView];
}
-(NSArray<MCChoice*>*)choices {
return _choices;
}
@synthesize identifier = _identifier;
-(void)setIdentifier:(NSString*)identifier {
if (![_identifier isEqualToString:identifier]) {
_identifier = identifier;
}
}
-(NSString*)identifier {
return _identifier;
}
@synthesize label = _label;
-(void)setLabel:(NSString*)label {
if (![_label isEqualToString:label]) {
@@ -51,42 +82,23 @@
return _label;
}
-(MCChoice*)findChoiceWithValue:(NSObject*)value
inArray:(NSArray*)array {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id element, NSDictionary *bindings) {
if (![element isKindOfClass:[MCChoice class]]) {
return NO;
}
MCChoice *choice = (MCChoice*)element;
return [choice.value isEqual:value];
}];
NSArray<MCChoice*> *matchingChoices = [_choices filteredArrayUsingPredicate:predicate];
MCChoice *foundChoice = matchingChoices.count > 0 ? matchingChoices.firstObject : nil;
return foundChoice;
}
@synthesize selectedValue = _selectedValue;
-(void)setSelectedValue:(NSObject*)value {
NSObject *newValue = nil;
MCChoice *foundChoice = [self findChoiceWithValue:value inArray:_choices];
if (!_choices) {
// choices hasn't been initialized yet so just set our selected value until choices is set
_selectedValue = value;
newValue = value;
} else if (!foundChoice) {
newValue = nil;
} else {
newValue = foundChoice.value;
}
MCChoice *foundChoice = [self findChoiceWithValue:value
inArray:_choices];
if (![_selectedChoice isEqual:foundChoice] || ![_selectedValue isEqual:foundChoice.value]) {
_selectedChoice = foundChoice;
_selectedValue = foundChoice.value;
if (_delegate) {
[_delegate editableValueDidChange:_selectedValue
forIdentifier:_identifier
andType:kMCFieldValueTypeChoice];
}
_selectedChoice = foundChoice;
if (_selectedValue != newValue) {
_selectedValue = newValue;
[self notifyChangedValue];
}
self.textField.text = _selectedChoice != nil
? _selectedChoice.label != nil
? _selectedChoice.label
: @""
: @"";
}
-(NSObject*)selectedValue {
return _selectedValue;
@@ -94,10 +106,11 @@
- (void)awakeFromNib {
[super awakeFromNib];
UIPickerView *childPicker = [[UIPickerView alloc] init];
childPicker.delegate = self;
childPicker.dataSource = self;
self.textField.inputView = childPicker;
self.pickerView = [[UIPickerView alloc] init];
self.pickerView.delegate = self;
self.pickerView.dataSource = self;
self.textField.inputView = self.pickerView;
self.pickerView.translatesAutoresizingMaskIntoConstraints = NO;
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar sizeToFit];
@@ -154,4 +167,10 @@ numberOfRowsInComponent:(NSInteger)component {
self.selectedValue = _selectedChoice.value;
}
#pragma mark - UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self updateView];
}
@end