diff --git a/iOS/MonsterCards.xcodeproj/project.pbxproj b/iOS/MonsterCards.xcodeproj/project.pbxproj index c6996f6..6589c75 100644 --- a/iOS/MonsterCards.xcodeproj/project.pbxproj +++ b/iOS/MonsterCards.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ E2E25805250CC3A7002E7308 /* MonsterCards.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = E2F7248225005E89007D87ED /* MonsterCards.xcdatamodeld */; }; E2E90AFF252015B3005241C8 /* MCSelectFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E2E90AFE252015B3005241C8 /* MCSelectFieldTableViewCell.m */; }; E2E90B0525201785005241C8 /* MCChoice.m in Sources */ = {isa = PBXBuildFile; fileRef = E2E90B0425201785005241C8 /* MCChoice.m */; }; + E2E90B172520667F005241C8 /* MCRadioFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E2E90B162520667E005241C8 /* MCRadioFieldTableViewCell.m */; }; E2ECA8F32504AC3300C1FFA5 /* SkillTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2ECA8F22504AC3300C1FFA5 /* SkillTests.m */; }; E2ECA8F52504BAAD00C1FFA5 /* MonsterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2ECA8F42504BAAD00C1FFA5 /* MonsterTests.m */; }; E2F7247525005E89007D87ED /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2F7247425005E89007D87ED /* AppDelegate.m */; }; @@ -128,6 +129,8 @@ E2E90AFE252015B3005241C8 /* MCSelectFieldTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCSelectFieldTableViewCell.m; sourceTree = ""; }; E2E90B0325201785005241C8 /* MCChoice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCChoice.h; sourceTree = ""; }; E2E90B0425201785005241C8 /* MCChoice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCChoice.m; sourceTree = ""; }; + E2E90B152520667E005241C8 /* MCRadioFieldTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCRadioFieldTableViewCell.h; sourceTree = ""; }; + E2E90B162520667E005241C8 /* MCRadioFieldTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCRadioFieldTableViewCell.m; sourceTree = ""; }; E2ECA8F22504AC3300C1FFA5 /* SkillTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SkillTests.m; sourceTree = ""; }; E2ECA8F42504BAAD00C1FFA5 /* MonsterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MonsterTests.m; sourceTree = ""; }; E2F7247025005E89007D87ED /* Monster Cards.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Monster Cards.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -288,6 +291,8 @@ E2805513251E03BE00C87527 /* MCBooleanFieldTableViewCell.m */, E20C315225146708003AB1AA /* MCIntegerFieldTableViewCell.h */, E20C315325146708003AB1AA /* MCIntegerFieldTableViewCell.m */, + E2E90B152520667E005241C8 /* MCRadioFieldTableViewCell.h */, + E2E90B162520667E005241C8 /* MCRadioFieldTableViewCell.m */, E2E90AFD252015B3005241C8 /* MCSelectFieldTableViewCell.h */, E2E90AFE252015B3005241C8 /* MCSelectFieldTableViewCell.m */, E2D3E3B22508C3360052A8EC /* MCShortStringFieldTableViewCell.h */, @@ -635,6 +640,7 @@ E25BD5FB250369D7007B04EF /* Skill.m in Sources */, E2E90B0525201785005241C8 /* MCChoice.m in Sources */, E2F7247825005E89007D87ED /* SceneDelegate.m in Sources */, + E2E90B172520667F005241C8 /* MCRadioFieldTableViewCell.m in Sources */, E20D032425031B9D00FB6E43 /* SearchViewController.m in Sources */, E22F837C2511D14E0072105C /* JSONHelper.m in Sources */, E25BD60125036BF8007B04EF /* Language.m in Sources */, diff --git a/iOS/MonsterCards/Base.lproj/Main.storyboard b/iOS/MonsterCards/Base.lproj/Main.storyboard index 84fe5db..bcbc13b 100644 --- a/iOS/MonsterCards/Base.lproj/Main.storyboard +++ b/iOS/MonsterCards/Base.lproj/Main.storyboard @@ -408,52 +408,99 @@ - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -463,7 +510,7 @@ - + @@ -493,14 +540,14 @@ - + - + - + diff --git a/iOS/MonsterCards/Models/Monster.h b/iOS/MonsterCards/Models/Monster.h index 66ef24f..24209dc 100644 --- a/iOS/MonsterCards/Models/Monster.h +++ b/iOS/MonsterCards/Models/Monster.h @@ -56,6 +56,14 @@ extern NSString* const kArmorNameSplintMail; extern NSString* const kArmorNamePlateMail; extern NSString* const kArmorNameOther; +extern NSString *const kProficiencyTypeNone; +extern NSString *const kProficiencyTypeProficient; +extern NSString *const kProficiencyTypeExpertise; + +extern NSString *const kAdvantageTypeNone; +extern NSString *const kAdvantageTypeAdvantage; +extern NSString *const kAdvantageTypeDisadvantage; + @class Skill; @interface Monster : NSManagedObject diff --git a/iOS/MonsterCards/Models/Monster.m b/iOS/MonsterCards/Models/Monster.m index 25ee106..c7acc16 100644 --- a/iOS/MonsterCards/Models/Monster.m +++ b/iOS/MonsterCards/Models/Monster.m @@ -63,6 +63,14 @@ NSString* const kMonsterSizeLarge = @"large"; NSString* const kMonsterSizeHuge = @"huge"; NSString* const kMonsterSizeGargantuan = @"gargantuan"; +NSString *const kProficiencyTypeNone = @"none"; +NSString *const kProficiencyTypeProficient = @"proficient"; +NSString *const kProficiencyTypeExpertise = @"expertise"; + +NSString *const kAdvantageTypeNone = @"none"; +NSString *const kAdvantageTypeAdvantage = @"advantage"; +NSString *const kAdvantageTypeDisadvantage = @"disadvantage"; + +(int)abilityModifierForScore: (int)score { return (int)floor((score - 10) / 2.0); } @@ -509,6 +517,18 @@ NSString* const kMonsterSizeGargantuan = @"gargantuan"; self.naturalArmorBonus = monster.naturalArmorBonus; self.hasShield = monster.hasShield; self.customArmor = monster.customArmor; + self.strengthSavingThrowAdvantage = monster.strengthSavingThrowAdvantage; + self.strengthSavingThrowProficiency = monster.strengthSavingThrowProficiency; + self.dexteritySavingThrowAdvantage = monster.dexteritySavingThrowAdvantage; + self.dexteritySavingThrowProficiency = monster.dexteritySavingThrowProficiency; + self.constitutionSavingThrowAdvantage = monster.constitutionSavingThrowAdvantage; + self.constitutionSavingThrowProficiency = monster.constitutionSavingThrowProficiency; + self.intelligenceSavingThrowAdvantage = monster.intelligenceSavingThrowAdvantage; + self.intelligenceSavingThrowProficiency = monster.intelligenceSavingThrowProficiency; + self.wisdomSavingThrowAdvantage = monster.wisdomSavingThrowAdvantage; + self.wisdomSavingThrowProficiency = monster.wisdomSavingThrowProficiency; + self.charismaSavingThrowAdvantage = monster.charismaSavingThrowAdvantage; + self.charismaSavingThrowProficiency = monster.charismaSavingThrowProficiency; } @end diff --git a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents index 9555877..a88b97f 100644 --- a/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents +++ b/iOS/MonsterCards/MonsterCards.xcdatamodeld/MonsterCards.xcdatamodel/contents @@ -6,31 +6,43 @@ + + + + + + + + + + + + - + \ No newline at end of file diff --git a/iOS/MonsterCards/Views/EditMonsterViewController.m b/iOS/MonsterCards/Views/EditMonsterViewController.m index 97aff14..bb90299 100644 --- a/iOS/MonsterCards/Views/EditMonsterViewController.m +++ b/iOS/MonsterCards/Views/EditMonsterViewController.m @@ -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* _armorTypes; + NSArray* _proficiencyTypes; + NSArray* _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 diff --git a/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.h b/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.h new file mode 100644 index 0000000..2bf614a --- /dev/null +++ b/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.h @@ -0,0 +1,29 @@ +// +// MCRadioFieldTableViewCell.h +// MonsterCards +// +// Created by Tom Hicks on 9/26/20. +// Copyright © 2020 Tom Hicks. All rights reserved. +// + +#import +#import "MCFormFieldDelegate.h" +#import "MCChoice.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MCRadioFieldTableViewCell : UITableViewCell + +@property NSString* identifier; +@property NSString* label; +@property NSObject* selectedValue; +@property NSArray* choices; + +@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) IBOutlet UILabel *labelView; +@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.m b/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.m new file mode 100644 index 0000000..913ec91 --- /dev/null +++ b/iOS/MonsterCards/Views/FormFields/MCRadioFieldTableViewCell.m @@ -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 *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*)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*)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 diff --git a/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.h b/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.h index 8d89ef6..47d11ac 100644 --- a/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.h +++ b/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.h @@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN @property (weak, nonatomic) id delegate; @property (weak, nonatomic) IBOutlet UITextField *textField; @property (weak, nonatomic) IBOutlet UILabel *labelView; +@property (nonatomic) UIPickerView *pickerView; @end diff --git a/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.m b/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.m index fe52804..8afc065 100644 --- a/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.m +++ b/iOS/MonsterCards/Views/FormFields/MCSelectFieldTableViewCell.m @@ -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 *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*)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*)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 *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