XLFormRowDescriptor.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. //
  2. // XLFormRowDescriptor.m
  3. // XLForm ( https://github.com/xmartlabs/XLForm )
  4. //
  5. // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
  6. //
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. // THE SOFTWARE.
  25. #import "XLForm.h"
  26. #import "XLFormViewController.h"
  27. #import "XLFormRowDescriptor.h"
  28. #import "NSString+XLFormAdditions.h"
  29. CGFloat XLFormUnspecifiedCellHeight = -3.0;
  30. CGFloat XLFormRowInitialHeight = -2;
  31. @interface XLFormDescriptor (_XLFormRowDescriptor)
  32. @property (readonly) NSDictionary* allRowsByTag;
  33. -(void)addObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
  34. -(void)removeObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
  35. @end
  36. @interface XLFormSectionDescriptor (_XLFormRowDescriptor)
  37. -(void)showFormRow:(XLFormRowDescriptor*)formRow;
  38. -(void)hideFormRow:(XLFormRowDescriptor*)formRow;
  39. @end
  40. #import "NSObject+XLFormAdditions.h"
  41. @interface XLFormRowDescriptor() <NSCopying>
  42. @property XLFormBaseCell * cell;
  43. @property (nonatomic) NSMutableArray *validators;
  44. @property BOOL isDirtyDisablePredicateCache;
  45. @property (nonatomic) NSNumber* disablePredicateCache;
  46. @property BOOL isDirtyHidePredicateCache;
  47. @property (nonatomic) NSNumber* hidePredicateCache;
  48. @end
  49. @implementation XLFormRowDescriptor
  50. @synthesize action = _action;
  51. @synthesize disabled = _disabled;
  52. @synthesize hidden = _hidden;
  53. @synthesize hidePredicateCache = _hidePredicateCache;
  54. @synthesize disablePredicateCache = _disablePredicateCache;
  55. @synthesize cellConfig = _cellConfig;
  56. @synthesize cellConfigForSelector = _cellConfigForSelector;
  57. @synthesize cellConfigIfDisabled = _cellConfigIfDisabled;
  58. @synthesize cellConfigAtConfigure = _cellConfigAtConfigure;
  59. @synthesize height = _height;
  60. -(instancetype)init
  61. {
  62. @throw [NSException exceptionWithName:NSGenericException reason:@"initWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title must be used" userInfo:nil];
  63. }
  64. -(instancetype)initWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title;
  65. {
  66. self = [super init];
  67. if (self){
  68. NSAssert(((![rowType isEqualToString:XLFormRowDescriptorTypeSelectorPopover] && ![rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelectorPopover]) || (([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) && ([rowType isEqualToString:XLFormRowDescriptorTypeSelectorPopover] || [rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelectorPopover]))), @"You must be running under UIUserInterfaceIdiomPad to use either XLFormRowDescriptorTypeSelectorPopover or XLFormRowDescriptorTypeMultipleSelectorPopover rows.");
  69. _tag = tag;
  70. _disabled = @NO;
  71. _hidden = @NO;
  72. _rowType = rowType;
  73. _title = title;
  74. _cellStyle = [rowType isEqualToString:XLFormRowDescriptorTypeButton] ? UITableViewCellStyleDefault : UITableViewCellStyleValue1;
  75. _validators = [NSMutableArray new];
  76. _cellConfig = [NSMutableDictionary dictionary];
  77. _cellConfigIfDisabled = [NSMutableDictionary dictionary];
  78. _cellConfigAtConfigure = [NSMutableDictionary dictionary];
  79. _isDirtyDisablePredicateCache = YES;
  80. _disablePredicateCache = nil;
  81. _isDirtyHidePredicateCache = YES;
  82. _hidePredicateCache = nil;
  83. _height = XLFormRowInitialHeight;
  84. [self addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
  85. [self addObserver:self forKeyPath:@"disablePredicateCache" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
  86. [self addObserver:self forKeyPath:@"hidePredicateCache" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
  87. }
  88. return self;
  89. }
  90. +(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType
  91. {
  92. return [[self class] formRowDescriptorWithTag:tag rowType:rowType title:nil];
  93. }
  94. +(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title
  95. {
  96. return [[[self class] alloc] initWithTag:tag rowType:rowType title:title];
  97. }
  98. -(XLFormBaseCell *)cellForFormController:(XLFormViewController * __unused)formController
  99. {
  100. if (!_cell){
  101. id cellClass = self.cellClass ?: [XLFormViewController cellClassesForRowDescriptorTypes][self.rowType];
  102. NSAssert(cellClass, @"Not defined XLFormRowDescriptorType: %@", self.rowType ?: @"");
  103. if ([cellClass isKindOfClass:[NSString class]]) {
  104. NSString *cellClassString = cellClass;
  105. NSString *cellResource = nil;
  106. NSBundle *bundle = nil;
  107. if ([cellClassString rangeOfString:@"/"].location != NSNotFound) {
  108. NSArray *components = [cellClassString componentsSeparatedByString:@"/"];
  109. cellResource = [components lastObject];
  110. NSString *folderName = [components firstObject];
  111. NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:folderName];
  112. bundle = [NSBundle bundleWithPath:bundlePath];
  113. } else {
  114. bundle = [NSBundle bundleForClass:NSClassFromString(cellClass)];
  115. cellResource = cellClassString;
  116. }
  117. NSParameterAssert(bundle != nil);
  118. NSParameterAssert(cellResource != nil);
  119. if ([bundle pathForResource:cellResource ofType:@"nib"]){
  120. _cell = [[bundle loadNibNamed:cellResource owner:nil options:nil] firstObject];
  121. }
  122. } else {
  123. _cell = [[cellClass alloc] initWithStyle:self.cellStyle reuseIdentifier:nil];
  124. }
  125. _cell.rowDescriptor = self;
  126. NSAssert([_cell isKindOfClass:[XLFormBaseCell class]], @"UITableViewCell must extend from XLFormBaseCell");
  127. [self configureCellAtCreationTime];
  128. }
  129. return _cell;
  130. }
  131. - (void)configureCellAtCreationTime
  132. {
  133. [self.cellConfigAtConfigure enumerateKeysAndObjectsUsingBlock:^(NSString *keyPath, id value, __unused BOOL *stop) {
  134. [_cell setValue:(value == [NSNull null]) ? nil : value forKeyPath:keyPath];
  135. }];
  136. }
  137. -(NSMutableDictionary *)cellConfig
  138. {
  139. if (_cellConfig) return _cellConfig;
  140. _cellConfig = [NSMutableDictionary dictionary];
  141. return _cellConfig;
  142. }
  143. -(NSMutableDictionary *)cellConfigForSelector
  144. {
  145. if (_cellConfigForSelector) return _cellConfigForSelector;
  146. _cellConfigForSelector = [NSMutableDictionary dictionary];
  147. return _cellConfigForSelector;
  148. }
  149. -(NSMutableDictionary *)cellConfigIfDisabled
  150. {
  151. if (_cellConfigIfDisabled) return _cellConfigIfDisabled;
  152. _cellConfigIfDisabled = [NSMutableDictionary dictionary];
  153. return _cellConfigIfDisabled;
  154. }
  155. -(NSMutableDictionary *)cellConfigAtConfigure
  156. {
  157. if (_cellConfigAtConfigure) return _cellConfigAtConfigure;
  158. _cellConfigAtConfigure = [NSMutableDictionary dictionary];
  159. return _cellConfigAtConfigure;
  160. }
  161. -(NSString*)editTextValue
  162. {
  163. if (self.value) {
  164. if (self.valueFormatter) {
  165. if (self.useValueFormatterDuringInput) {
  166. return [self displayTextValue];
  167. }else{
  168. // have formatter, but we don't want to use it during editing
  169. return [self.value displayText];
  170. }
  171. }else{
  172. // have value, but no formatter, use the value's displayText
  173. return [self.value displayText];
  174. }
  175. }else{
  176. // placeholder
  177. return @"";
  178. }
  179. }
  180. -(NSString*)displayTextValue
  181. {
  182. if (self.value) {
  183. if (self.valueFormatter) {
  184. return [self.valueFormatter stringForObjectValue:self.value];
  185. }
  186. else{
  187. return [self.value displayText];
  188. }
  189. }
  190. else {
  191. return self.noValueDisplayText;
  192. }
  193. }
  194. -(NSString *)description
  195. {
  196. return self.tag; // [NSString stringWithFormat:@"%@ - %@ (%@)", [super description], self.tag, self.rowType];
  197. }
  198. -(XLFormAction *)action
  199. {
  200. if (!_action){
  201. _action = [[XLFormAction alloc] init];
  202. }
  203. return _action;
  204. }
  205. -(void)setAction:(XLFormAction *)action
  206. {
  207. _action = action;
  208. }
  209. -(CGFloat)height
  210. {
  211. if (_height == XLFormRowInitialHeight){
  212. if ([[self.cell class] respondsToSelector:@selector(formDescriptorCellHeightForRowDescriptor:)]){
  213. return [[self.cell class] formDescriptorCellHeightForRowDescriptor:self];
  214. } else {
  215. _height = XLFormUnspecifiedCellHeight;
  216. }
  217. }
  218. return _height;
  219. }
  220. -(void)setHeight:(CGFloat)height {
  221. _height = height;
  222. }
  223. // In the implementation
  224. -(id)copyWithZone:(NSZone *)zone
  225. {
  226. XLFormRowDescriptor * rowDescriptorCopy = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:[self.rowType copy] title:[self.title copy]];
  227. rowDescriptorCopy.cellClass = [self.cellClass copy];
  228. [rowDescriptorCopy.cellConfig addEntriesFromDictionary:self.cellConfig];
  229. [rowDescriptorCopy.cellConfigAtConfigure addEntriesFromDictionary:self.cellConfigAtConfigure];
  230. rowDescriptorCopy.valueTransformer = [self.valueTransformer copy];
  231. rowDescriptorCopy->_hidden = _hidden;
  232. rowDescriptorCopy->_disabled = _disabled;
  233. rowDescriptorCopy.required = self.isRequired;
  234. rowDescriptorCopy.isDirtyDisablePredicateCache = YES;
  235. rowDescriptorCopy.isDirtyHidePredicateCache = YES;
  236. rowDescriptorCopy.validators = [self.validators mutableCopy];
  237. // =====================
  238. // properties for Button
  239. // =====================
  240. rowDescriptorCopy.action = [self.action copy];
  241. // ===========================
  242. // property used for Selectors
  243. // ===========================
  244. rowDescriptorCopy.noValueDisplayText = [self.noValueDisplayText copy];
  245. rowDescriptorCopy.selectorTitle = [self.selectorTitle copy];
  246. rowDescriptorCopy.selectorOptions = [self.selectorOptions copy];
  247. rowDescriptorCopy.leftRightSelectorLeftOptionSelected = [self.leftRightSelectorLeftOptionSelected copy];
  248. return rowDescriptorCopy;
  249. }
  250. -(void)dealloc
  251. {
  252. [self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeDisabled];
  253. [self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
  254. @try {
  255. [self removeObserver:self forKeyPath:@"value"];
  256. }
  257. @catch (NSException * __unused exception) {}
  258. @try {
  259. [self removeObserver:self forKeyPath:@"disablePredicateCache"];
  260. }
  261. @catch (NSException * __unused exception) {}
  262. @try {
  263. [self removeObserver:self forKeyPath:@"hidePredicateCache"];
  264. }
  265. @catch (NSException * __unused exception) {}
  266. }
  267. #pragma mark - KVO
  268. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
  269. {
  270. if (!self.sectionDescriptor) return;
  271. if (object == self && ([keyPath isEqualToString:@"value"] || [keyPath isEqualToString:@"hidePredicateCache"] || [keyPath isEqualToString:@"disablePredicateCache"])){
  272. if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeSetting)]){
  273. id newValue = [change objectForKey:NSKeyValueChangeNewKey];
  274. id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
  275. if ([keyPath isEqualToString:@"value"]){
  276. [self.sectionDescriptor.formDescriptor.delegate formRowDescriptorValueHasChanged:object oldValue:oldValue newValue:newValue];
  277. if (self.onChangeBlock) {
  278. self.onChangeBlock(oldValue, newValue, self);
  279. }
  280. }
  281. else{
  282. [self.sectionDescriptor.formDescriptor.delegate formRowDescriptorPredicateHasChanged:object oldValue:oldValue newValue:newValue predicateType:([keyPath isEqualToString:@"hidePredicateCache"] ? XLPredicateTypeHidden : XLPredicateTypeDisabled)];
  283. }
  284. }
  285. }
  286. }
  287. #pragma mark - Disable Predicate functions
  288. -(BOOL)isDisabled
  289. {
  290. if (self.sectionDescriptor.formDescriptor.isDisabled){
  291. return YES;
  292. }
  293. if (self.isDirtyDisablePredicateCache) {
  294. [self evaluateIsDisabled];
  295. }
  296. return [self.disablePredicateCache boolValue];
  297. }
  298. -(void)setDisabled:(id)disabled
  299. {
  300. if ([_disabled isKindOfClass:[NSPredicate class]]){
  301. [self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeDisabled];
  302. }
  303. _disabled = [disabled isKindOfClass:[NSString class]] ? [disabled formPredicate] : disabled;
  304. if ([_disabled isKindOfClass:[NSPredicate class]]){
  305. [self.sectionDescriptor.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeDisabled];
  306. }
  307. [self evaluateIsDisabled];
  308. }
  309. -(BOOL)evaluateIsDisabled
  310. {
  311. if ([_disabled isKindOfClass:[NSPredicate class]]) {
  312. if (!self.sectionDescriptor.formDescriptor) {
  313. self.isDirtyDisablePredicateCache = YES;
  314. } else {
  315. @try {
  316. self.disablePredicateCache = @([_disabled evaluateWithObject:self substitutionVariables:self.sectionDescriptor.formDescriptor.allRowsByTag ?: @{}]);
  317. }
  318. @catch (NSException *exception) {
  319. // predicate syntax error.
  320. self.isDirtyDisablePredicateCache = YES;
  321. };
  322. }
  323. }
  324. else{
  325. self.disablePredicateCache = _disabled;
  326. }
  327. if ([self.disablePredicateCache boolValue]){
  328. [self.cell resignFirstResponder];
  329. }
  330. return [self.disablePredicateCache boolValue];
  331. }
  332. -(id)disabled
  333. {
  334. return _disabled;
  335. }
  336. -(void)setDisablePredicateCache:(NSNumber*)disablePredicateCache
  337. {
  338. NSParameterAssert(disablePredicateCache);
  339. self.isDirtyDisablePredicateCache = NO;
  340. if (!_disablePredicateCache || ![_disablePredicateCache isEqualToNumber:disablePredicateCache]){
  341. _disablePredicateCache = disablePredicateCache;
  342. }
  343. }
  344. -(NSNumber*)disablePredicateCache
  345. {
  346. return _disablePredicateCache;
  347. }
  348. #pragma mark - Hide Predicate functions
  349. -(NSNumber *)hidePredicateCache
  350. {
  351. return _hidePredicateCache;
  352. }
  353. -(void)setHidePredicateCache:(NSNumber *)hidePredicateCache
  354. {
  355. NSParameterAssert(hidePredicateCache);
  356. self.isDirtyHidePredicateCache = NO;
  357. if (!_hidePredicateCache || ![_hidePredicateCache isEqualToNumber:hidePredicateCache]){
  358. _hidePredicateCache = hidePredicateCache;
  359. }
  360. }
  361. -(BOOL)isHidden
  362. {
  363. if (self.isDirtyHidePredicateCache) {
  364. return [self evaluateIsHidden];
  365. }
  366. return [self.hidePredicateCache boolValue];
  367. }
  368. -(BOOL)evaluateIsHidden
  369. {
  370. if ([_hidden isKindOfClass:[NSPredicate class]]) {
  371. if (!self.sectionDescriptor.formDescriptor) {
  372. self.isDirtyHidePredicateCache = YES;
  373. } else {
  374. @try {
  375. self.hidePredicateCache = @([_hidden evaluateWithObject:self substitutionVariables:self.sectionDescriptor.formDescriptor.allRowsByTag ?: @{}]);
  376. }
  377. @catch (NSException *exception) {
  378. // predicate syntax error or for has not finished loading.
  379. self.isDirtyHidePredicateCache = YES;
  380. };
  381. }
  382. }
  383. else{
  384. self.hidePredicateCache = _hidden;
  385. }
  386. if ([self.hidePredicateCache boolValue]){
  387. [self.cell resignFirstResponder];
  388. [self.sectionDescriptor hideFormRow:self];
  389. }
  390. else{
  391. [self.sectionDescriptor showFormRow:self];
  392. }
  393. return [self.hidePredicateCache boolValue];
  394. }
  395. -(void)setHidden:(id)hidden
  396. {
  397. if ([_hidden isKindOfClass:[NSPredicate class]]){
  398. [self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
  399. }
  400. _hidden = [hidden isKindOfClass:[NSString class]] ? [hidden formPredicate] : hidden;
  401. if ([_hidden isKindOfClass:[NSPredicate class]]){
  402. [self.sectionDescriptor.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeHidden];
  403. }
  404. [self evaluateIsHidden]; // check and update if this row should be hidden.
  405. }
  406. -(id)hidden
  407. {
  408. return _hidden;
  409. }
  410. #pragma mark - validation
  411. -(void)addValidator:(id<XLFormValidatorProtocol>)validator
  412. {
  413. if (validator == nil || ![validator conformsToProtocol:@protocol(XLFormValidatorProtocol)])
  414. return;
  415. if(![self.validators containsObject:validator]) {
  416. [self.validators addObject:validator];
  417. }
  418. }
  419. -(void)removeValidator:(id<XLFormValidatorProtocol>)validator
  420. {
  421. if (validator == nil|| ![validator conformsToProtocol:@protocol(XLFormValidatorProtocol)])
  422. return;
  423. if ([self.validators containsObject:validator]) {
  424. [self.validators removeObject:validator];
  425. }
  426. }
  427. - (BOOL)valueIsEmpty
  428. {
  429. return self.value == nil || [self.value isKindOfClass:[NSNull class]] || ([self.value respondsToSelector:@selector(length)] && [self.value length]==0) ||
  430. ([self.value respondsToSelector:@selector(count)] && [self.value count]==0);
  431. }
  432. -(XLFormValidationStatus *)doValidation
  433. {
  434. XLFormValidationStatus *valStatus = nil;
  435. if (self.required) {
  436. // do required validation here
  437. if ([self valueIsEmpty]) {
  438. valStatus = [XLFormValidationStatus formValidationStatusWithMsg:@"" status:NO rowDescriptor:self];
  439. NSString *msg = nil;
  440. if (self.requireMsg != nil) {
  441. msg = self.requireMsg;
  442. } else {
  443. // default message for required msg
  444. msg = NSLocalizedString(@"%@ can't be empty", nil);
  445. }
  446. if (self.title != nil) {
  447. valStatus.msg = [NSString stringWithFormat:msg, self.title];
  448. } else {
  449. valStatus.msg = [NSString stringWithFormat:msg, self.tag];
  450. }
  451. return valStatus;
  452. }
  453. }
  454. // custom validator
  455. for(id<XLFormValidatorProtocol> v in self.validators) {
  456. if ([v conformsToProtocol:@protocol(XLFormValidatorProtocol)]) {
  457. XLFormValidationStatus *vStatus = [v isValid:self];
  458. // fail validation
  459. if (vStatus != nil && !vStatus.isValid) {
  460. return vStatus;
  461. }
  462. valStatus = vStatus;
  463. } else {
  464. valStatus = nil;
  465. }
  466. }
  467. return valStatus;
  468. }
  469. #pragma mark - Deprecations
  470. -(void)setButtonViewController:(Class)buttonViewController
  471. {
  472. self.action.viewControllerClass = buttonViewController;
  473. }
  474. -(Class)buttonViewController
  475. {
  476. return self.action.viewControllerClass;
  477. }
  478. -(void)setSelectorControllerClass:(Class)selectorControllerClass
  479. {
  480. self.action.viewControllerClass = selectorControllerClass;
  481. }
  482. -(Class)selectorControllerClass
  483. {
  484. return self.action.viewControllerClass;
  485. }
  486. -(void)setButtonViewControllerPresentationMode:(XLFormPresentationMode)buttonViewControllerPresentationMode
  487. {
  488. self.action.viewControllerPresentationMode = buttonViewControllerPresentationMode;
  489. }
  490. -(XLFormPresentationMode)buttonViewControllerPresentationMode
  491. {
  492. return self.action.viewControllerPresentationMode;
  493. }
  494. @end
  495. @implementation XLFormLeftRightSelectorOption
  496. +(XLFormLeftRightSelectorOption *)formLeftRightSelectorOptionWithLeftValue:(id)leftValue
  497. httpParameterKey:(NSString *)httpParameterKey
  498. rightOptions:(NSArray *)rightOptions;
  499. {
  500. return [[XLFormLeftRightSelectorOption alloc] initWithLeftValue:leftValue
  501. httpParameterKey:httpParameterKey
  502. rightOptions:rightOptions];
  503. }
  504. -(instancetype)initWithLeftValue:(NSString *)leftValue httpParameterKey:(NSString *)httpParameterKey rightOptions:(NSArray *)rightOptions
  505. {
  506. self = [super init];
  507. if (self){
  508. _selectorTitle = nil;
  509. _leftValue = leftValue;
  510. _rightOptions = rightOptions;
  511. _httpParameterKey = httpParameterKey;
  512. }
  513. return self;
  514. }
  515. @end
  516. @implementation XLFormAction
  517. - (instancetype)init
  518. {
  519. self = [super init];
  520. if (self) {
  521. _viewControllerPresentationMode = XLFormPresentationModeDefault;
  522. }
  523. return self;
  524. }
  525. // In the implementation
  526. -(id)copyWithZone:(NSZone *)zone
  527. {
  528. XLFormAction * actionCopy = [[XLFormAction alloc] init];
  529. actionCopy.viewControllerPresentationMode = self.viewControllerPresentationMode;
  530. if (self.viewControllerClass){
  531. actionCopy.viewControllerClass = [self.viewControllerClass copy];
  532. }
  533. else if ([self.viewControllerStoryboardId length] != 0){
  534. actionCopy.viewControllerStoryboardId = [self.viewControllerStoryboardId copy];
  535. }
  536. else if ([self.viewControllerNibName length] != 0){
  537. actionCopy.viewControllerNibName = [self.viewControllerNibName copy];
  538. }
  539. if (self.formBlock){
  540. actionCopy.formBlock = [self.formBlock copy];
  541. }
  542. else if (self.formSelector){
  543. actionCopy.formSelector = self.formSelector;
  544. }
  545. else if (self.formSegueIdentifier){
  546. actionCopy.formSegueIdentifier = [self.formSegueIdentifier copy];
  547. }
  548. else if (self.formSegueClass){
  549. actionCopy.formSegueClass = [self.formSegueClass copy];
  550. }
  551. return actionCopy;
  552. }
  553. -(void)setViewControllerClass:(Class)viewControllerClass
  554. {
  555. _viewControllerClass = viewControllerClass;
  556. _viewControllerNibName = nil;
  557. _viewControllerStoryboardId = nil;
  558. }
  559. -(void)setViewControllerNibName:(NSString *)viewControllerNibName
  560. {
  561. _viewControllerClass = nil;
  562. _viewControllerNibName = viewControllerNibName;
  563. _viewControllerStoryboardId = nil;
  564. }
  565. -(void)setViewControllerStoryboardId:(NSString *)viewControllerStoryboardId
  566. {
  567. _viewControllerClass = nil;
  568. _viewControllerNibName = nil;
  569. _viewControllerStoryboardId = viewControllerStoryboardId;
  570. }
  571. -(void)setFormSelector:(SEL)formSelector
  572. {
  573. _formBlock = nil;
  574. _formSegueClass = nil;
  575. _formSegueIdentifier = nil;
  576. _formSelector = formSelector;
  577. }
  578. -(void)setFormBlock:(void (^)(XLFormRowDescriptor *))formBlock
  579. {
  580. _formSegueClass = nil;
  581. _formSegueIdentifier = nil;
  582. _formSelector = nil;
  583. _formBlock = formBlock;
  584. }
  585. -(void)setFormSegueClass:(Class)formSegueClass
  586. {
  587. _formSelector = nil;
  588. _formBlock = nil;
  589. _formSegueIdentifier = nil;
  590. _formSegueClass = formSegueClass;
  591. }
  592. -(void)setFormSegueIdentifier:(NSString *)formSegueIdentifier
  593. {
  594. _formSelector = nil;
  595. _formBlock = nil;
  596. _formSegueClass = nil;
  597. _formSegueIdentifier = formSegueIdentifier;
  598. }
  599. // Deprecated:
  600. -(void)setFormSegueIdenfifier:(NSString *)formSegueIdenfifier
  601. {
  602. self.formSegueIdentifier = formSegueIdenfifier;
  603. }
  604. -(NSString *)formSegueIdenfifier
  605. {
  606. return self.formSegueIdentifier;
  607. }
  608. @end