RulesConditionViewController.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. //
  2. // RulesConditionViewController.m
  3. // kneet2
  4. //
  5. // Created by Jason Lee on 11/25/15.
  6. // Copyright © 2015 ntels. All rights reserved.
  7. //
  8. #import "JDObject.h"
  9. #import "ItemModel.h"
  10. #import "CustomTableView.h"
  11. #import "CustomLabel.h"
  12. #import "CustomButton.h"
  13. #import "CustomImageView.h"
  14. #import "RulesConditionHomeModePopupView.h"
  15. #import "RulesAddViewController.h"
  16. #import "DeviceSelectPopupView.h"
  17. #import "DeviceNodePopupView.h"
  18. #import "UIImageView+WebCache.h"
  19. #import "RulesConditionViewController.h"
  20. #import "DurationPopupView.h"
  21. @implementation RulesConditionHeaderTableViewCell
  22. @end
  23. @implementation RulesConditionDeviceTableViewCell
  24. @end
  25. @implementation RulesConditionTableViewCell
  26. @end
  27. @implementation RulesConditionFooterTableViewCell
  28. @end
  29. @interface RulesConditionViewController () <UITableViewDataSource, UITableViewDelegate> {
  30. CustomButton *_btnModeAdd, *_btnDurationAdd;
  31. NSMutableArray *_arrayForHeader, *_arrayForFooter;
  32. RulesConditionHomeModePopupView *_mpopup;
  33. DurationPopupView *_dpopup;
  34. }
  35. @property (weak, nonatomic, readonly) NSMutableArray<ItemSubModel> *modes;
  36. @property (weak, nonatomic, readonly) NSMutableArray<ItemSubModel> *durations;
  37. @property (weak, nonatomic, readonly) NSMutableArray<ItemSubModel> *pdevices;
  38. @end
  39. #pragma mark - Class Definition
  40. @implementation RulesConditionViewController
  41. - (void)viewDidLoad {
  42. [super viewDidLoad];
  43. // Do any additional setup after loading the view.
  44. [self initProperties];
  45. [self initUI];
  46. [self prepareViewDidLoad];
  47. }
  48. - (void)initProperties {
  49. _arrayForHeader = [[NSMutableArray alloc] init];
  50. _arrayForFooter = [[NSMutableArray alloc] init];
  51. }
  52. - (void)initUI {
  53. [self initTableViewAsDefaultStyle:_tableView];
  54. _tableView.scrollEnabled = NO;
  55. }
  56. - (void)prepareViewDidLoad {
  57. }
  58. - (CGFloat)tableHeight {
  59. CGFloat height = _isShowingMode ? 0 : (63 * 3) + 45;
  60. if (_isShowingMode) {//규칙 상세일 경우,
  61. height = self.modes.count > 0 ? height + 86 + 63 + 15: height; //add row height + header height + footer
  62. height = self.durations.count > 0 ? height + 86 + 63 + 15: height;
  63. height = self.pdevices.count > 0 ? height + (86 * self.pdevices.count) + 63 + 15 : height;
  64. } else {
  65. height = self.modes.count > 0 ? height + 86 : height;
  66. height = self.durations.count > 0 ? height + 86 : height;
  67. height = self.pdevices.count > 0 ? height + (86 * self.pdevices.count) : height;
  68. }
  69. return height;
  70. }
  71. #pragma mark - Main Logic
  72. - (NSMutableArray<ItemSubModel> *)modes {
  73. ItemModel *mode = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeHomeMode];
  74. return mode.subItems;
  75. }
  76. - (NSMutableArray<ItemSubModel> *)durations {
  77. ItemModel *duration = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDueDate];
  78. return duration.subItems;
  79. }
  80. - (NSMutableArray<ItemSubModel> *)pdevices {
  81. ItemModel *pdevice = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  82. return pdevice.subItems;
  83. }
  84. #pragma mark - UITableView DataSource & Delegate
  85. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  86. return 3;
  87. }
  88. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  89. NSInteger count = 0;
  90. if (section == 0) {//mode
  91. count = self.modes.count;
  92. } else if (section == 1) {//duration
  93. count = self.durations.count;
  94. } else if (section == 2) {//device
  95. count = self.pdevices.count;
  96. }
  97. return count;
  98. }
  99. - (NSString *)headerTitleForSection:(NSInteger)section {
  100. NSString *title = nil;
  101. if (section == 0) {//mode
  102. title = @"이 홈모드에서만";
  103. } else if (section == 1) {//duration
  104. title = @"이 기간동안만";
  105. } else if (section == 2) {//devices
  106. title = @"이 장치가 특정 상태일 때만";
  107. }
  108. return title;
  109. }
  110. - (void)addTargetToHeaderAddButton:(CustomButton *)btnAdd section:(NSInteger)section {
  111. if (section == 0) {
  112. if (!_btnModeAdd) {
  113. _btnModeAdd = btnAdd;
  114. [btnAdd addTarget:self action:@selector(btnAddModeTouched:) forControlEvents:UIControlEventTouchUpInside];
  115. }
  116. } else if (section == 1) {
  117. if (!_btnDurationAdd) {
  118. _btnDurationAdd = btnAdd;
  119. [btnAdd addTarget:self action:@selector(btnAddDurationTouched:) forControlEvents:UIControlEventTouchUpInside];
  120. }
  121. } else if (section == 2) {
  122. [btnAdd addTarget:self action:@selector(btnAddDeviceTouched:) forControlEvents:UIControlEventTouchUpInside];
  123. }
  124. }
  125. - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
  126. BOOL hasHeader = !_isShowingMode;
  127. if (section == 0) {//모드
  128. hasHeader = self.modes.count || !_isShowingMode; //상세에서 해당 항목이 없는 경우, 표시하지 않기 위해 사용 - isShowingMode
  129. } else if (section == 1) {//기간
  130. hasHeader = self.durations.count || !_isShowingMode;
  131. } else if (section == 2) {//장치
  132. hasHeader = self.pdevices.count || !_isShowingMode;
  133. }
  134. UIView *view = _arrayForHeader.count > section ? _arrayForHeader[section] : nil;
  135. if (!view) {
  136. if (hasHeader) {
  137. RulesConditionHeaderTableViewCell *hcell = (RulesConditionHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"HeaderCellIdentifier"];
  138. hcell.width = IPHONE_WIDTH;
  139. view = [[UIView alloc] initWithFrame:hcell.contentView.frame];
  140. [view addSubview:hcell];
  141. hcell.lblTitle.text = [self headerTitleForSection:section];
  142. hcell.btnAdd.hidden = _isShowingMode;
  143. if (!hcell.btnAdd.hidden && ![hcell.btnAdd actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  144. [self addTargetToHeaderAddButton:hcell.btnAdd section:section];
  145. }
  146. } else {
  147. view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, CGFLOAT_MIN)];
  148. }
  149. if (_arrayForHeader.count == section) {
  150. [_arrayForHeader insertObject:view atIndex:section];
  151. }
  152. } else {
  153. if (hasHeader) {
  154. RulesConditionHeaderTableViewCell *hcell = (RulesConditionHeaderTableViewCell *)view.subviews[0];
  155. hcell.lblTitle.text = hcell.lblTitle.text = [self headerTitleForSection:section];
  156. }
  157. }
  158. if (!_isShowingMode) {
  159. [self checkHeaderButton:section];
  160. }
  161. return view;
  162. }
  163. - (void)checkHeaderButton:(NSInteger)section {
  164. if (section == 0) {//모드
  165. _btnModeAdd.hidden = self.modes.count > 0;
  166. } else if (section == 1) {//기간
  167. _btnDurationAdd.hidden = self.durations.count > 0;
  168. }
  169. }
  170. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
  171. BOOL hasHeader = !_isShowingMode;
  172. CGFloat adjustHeight = 0.0f;
  173. if (section == 0) {
  174. hasHeader = self.modes.count || !_isShowingMode;
  175. } else if (section == 1) {
  176. hasHeader = self.durations.count || !_isShowingMode;
  177. adjustHeight = 0.0f;
  178. } else if (section == 2) {
  179. hasHeader = self.pdevices.count || !_isShowingMode;
  180. adjustHeight = 0.0f;
  181. }
  182. return hasHeader ? 63.0f + adjustHeight : CGFLOAT_MIN;
  183. }
  184. - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
  185. BOOL hasFooter = !_isShowingMode;
  186. if (section == 0) {
  187. hasFooter = self.modes.count;// || !_isShowingMode;
  188. } else if (section == 1) {
  189. hasFooter = self.durations.count;// || !_isShowingMode;
  190. } else if (section == 2) {
  191. hasFooter = self.pdevices.count;// || !_isShowingMode;
  192. }
  193. UIView *view = _arrayForFooter.count > section ? _arrayForFooter[section] : nil;
  194. if (!view) {
  195. if (hasFooter) {
  196. RulesConditionFooterTableViewCell *hcell = (RulesConditionFooterTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"FooterCellIdentifier"];
  197. hcell.width = IPHONE_WIDTH;
  198. view = [[UIView alloc] initWithFrame:hcell.contentView.frame];
  199. [view addSubview:hcell];
  200. } else {
  201. view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, CGFLOAT_MIN)];
  202. }
  203. if (_arrayForHeader.count == section) {
  204. [_arrayForHeader insertObject:view atIndex:section];
  205. }
  206. }
  207. return view;
  208. }
  209. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
  210. BOOL hasFooter = !_isShowingMode;
  211. if (section == 0) {
  212. hasFooter = self.modes.count;// || !_isShowingMode;
  213. } else if (section == 1) {
  214. hasFooter = self.durations.count;// || !_isShowingMode;
  215. } else if (section == 2) {
  216. hasFooter = self.pdevices.count;// || !_isShowingMode;
  217. }
  218. return hasFooter ? 15.0f : CGFLOAT_MIN;
  219. }
  220. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  221. CGFloat height = 86.0f;
  222. return height;
  223. }
  224. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  225. UITableViewCell *cell = nil;
  226. NSInteger section = indexPath.section;
  227. if (section == 0) {//mode
  228. ItemSubModel *subCondition = self.modes[0];
  229. RulesConditionTableViewCell *tcell = (RulesConditionTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"ConditionCellIdentifier"];
  230. tcell.lblItem.text = subCondition.cmdclsValueMsg;
  231. [tcell.imgvIcon setImage:[UIImage imageNamed:@"img_rule_icon_homemode"]];
  232. tcell.btnDelete.hidden = _isShowingMode;
  233. if (!tcell.btnDelete.hidden) {
  234. tcell.btnDelete.value = subCondition;
  235. [tcell.btnDelete addTarget:self action:@selector(btnDeleteModeTouched:) forControlEvents:UIControlEventTouchUpInside];
  236. }
  237. tcell.bottomLine.hidden = YES;
  238. cell = tcell;
  239. } else if (section == 1) {//duration
  240. ItemSubModel *subCondition = self.durations[0];
  241. RulesConditionTableViewCell *tcell = (RulesConditionTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"ConditionCellIdentifier"];\
  242. NSArray *dueDates = [subCondition.cmdclsValue componentsSeparatedByString:@"~"];
  243. tcell.lblItem.text = [NSString stringWithFormat:@"%@ ~ %@", dueDates.firstObject, dueDates.lastObject];
  244. [tcell.imgvIcon setImage:[UIImage imageNamed:@"img_rule_icon_calendar"]];
  245. tcell.btnDelete.hidden = _isShowingMode;
  246. if (!tcell.btnDelete.hidden) {
  247. tcell.btnDelete.value = subCondition;
  248. [tcell.btnDelete addTarget:self action:@selector(btnDeleteDurationTouched:) forControlEvents:UIControlEventTouchUpInside];
  249. }
  250. tcell.bottomLine.hidden = YES;
  251. cell = tcell;
  252. } else if (section == 2) {//action
  253. RulesConditionDeviceTableViewCell *tcell = (RulesConditionDeviceTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"DeviceCellIdentifier"];
  254. ItemSubModel *subItem = self.pdevices[indexPath.row];
  255. tcell.lblItem.text = subItem.sourceName;
  256. if ([subItem.deleteYn boolValue]) {//삭제된 노드가 있을 경우,
  257. [tcell.lblItem setStrikethrough:tcell.lblItem.text];
  258. }
  259. tcell.lblSubItem.text = subItem.sourceSubName;
  260. [tcell.imgvIcon sd_setImageWithURL:[NSURL URLWithString:subItem.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached];
  261. //노드의 액션 값을 세팅함.
  262. if (subItem.cmdclsValueList && subItem.cmdclsValueList.count) {//커맨드클래스 밸루 리스트가 있을 경우,
  263. CmdClsValueModel *cmdclsValue = [subItem.cmdclsValueList matchedObjectName:ksCustomRadioButtonStatus condition:YES];
  264. tcell.lblCondition.text = cmdclsValue.cmdclsValueMsg;
  265. } else {
  266. if (subItem.cmdclsValueMsg) {
  267. tcell.lblCondition.text = subItem.cmdclsValueMsg;
  268. } else {
  269. NSString *condition = [subItem.conditionTypeCode isEqualToString:ksConditionTypeCodeGreatOrEqual] ? @"이상" : @"이하";
  270. tcell.lblCondition.text = [NSString stringWithFormat:@"%@%@ %@", subItem.cmdclsValue, subItem.unit, condition];
  271. }
  272. }
  273. if (!_isShowingMode) {
  274. [tcell.lblCondition setUnderLine:tcell.lblCondition.text];
  275. }
  276. tcell.btnDelete.hidden = _isShowingMode;
  277. if (!tcell.btnDelete.hidden) {
  278. tcell.btnDelete.value = subItem;
  279. if (![tcell.btnDelete actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  280. [tcell.btnDelete addTarget:self action:@selector(btnDeleteDeviceTouched:) forControlEvents:UIControlEventTouchUpInside];
  281. }
  282. } else {
  283. tcell.constraintConditionLabelRight.constant = 15.0f;
  284. }
  285. tcell.bottomLine.hidden = !(indexPath.row < self.pdevices.count);
  286. cell = tcell;
  287. }
  288. return cell;
  289. }
  290. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  291. [super tableView:tableView didSelectRowAtIndexPath:indexPath];
  292. if (_isShowingMode) {
  293. return;
  294. }
  295. if (indexPath.section == 2) {//actions
  296. ItemSubModel *subItem = self.pdevices[indexPath.row];
  297. [RulesAddViewController modifyAction:subItem refDevices:_refDevices tableView:_tableView];
  298. }
  299. }
  300. #pragma mark - Table Events
  301. - (void)btnAddModeTouched:(id)sender {
  302. ItemModel *mode = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeHomeMode];
  303. BOOL isNewTrigger = mode == nil;
  304. mode = isNewTrigger ? [[ItemModel alloc] init] : mode;
  305. if (!_mpopup) {
  306. _mpopup = [[RulesConditionHomeModePopupView alloc] initFromNib];
  307. }
  308. _mpopup.condition = mode;
  309. [_mpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  310. if (buttonIndex == 0) {//OK
  311. if (isNewTrigger) {
  312. [_conditions addObject:mode];
  313. }
  314. [self updateTableView];
  315. }
  316. }];
  317. }
  318. - (void)btnAddDurationTouched:(id)sender {
  319. ItemModel *dueDate = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDueDate];
  320. BOOL isNewTrigger = dueDate == nil;
  321. dueDate = isNewTrigger ? [[ItemModel alloc] init] : dueDate;
  322. if (!_dpopup) {
  323. _dpopup = [[DurationPopupView alloc] initFromNib];
  324. }
  325. _dpopup.condition = dueDate;
  326. [_dpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  327. if (buttonIndex == 0) {//OK
  328. if (isNewTrigger) {
  329. [_conditions addObject:dueDate];
  330. }
  331. [self updateTableView];
  332. }
  333. }];
  334. }
  335. - (void)btnAddDeviceTouched:(id)sender {
  336. ItemModel *deviceCondition = (ItemModel *)[_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice];
  337. BOOL isNewTrigger = deviceCondition == nil;
  338. deviceCondition = isNewTrigger ? [[ItemModel alloc] init] : deviceCondition;
  339. DeviceSelectPopupView *dpopup = [[DeviceSelectPopupView alloc] initFromNib];
  340. dpopup.refDevices = _refDevices;
  341. dpopup.typeCode = ksItemTypeCodeTrigger;
  342. [dpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  343. if (buttonIndex == 0) {//ok
  344. DeviceNodePopupView *npopup = [[DeviceNodePopupView alloc] initFromNib];
  345. npopup.refDevice = dpopup.selectedDevices[0];
  346. npopup.typeCode = ksItemTypeCodeTrigger;
  347. [npopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  348. //action add
  349. if (buttonIndex == 0) {//OK
  350. if (isNewTrigger) {
  351. deviceCondition.itemName = @"이 장치가 특정 상태일 때만";
  352. deviceCondition.itemSubTypeCode = ksItemSubTypeCodeDevice; //트리거 타입 설정
  353. deviceCondition.subItems = [(NSMutableArray<ItemSubModel> *)[NSMutableArray alloc] init];
  354. [_conditions addObject:deviceCondition];
  355. }
  356. ItemSubModel *snode = npopup.selectedNode;
  357. //존재 여부 확인
  358. if (![deviceCondition.subItems objectByUsingPredicateFormat:@"sourceId == %@ && sourceSubId == %@", snode.sourceId, snode.sourceSubId]) {
  359. [deviceCondition.subItems addObject: snode];
  360. }
  361. [self updateTableView];
  362. }
  363. }];
  364. }
  365. }];
  366. }
  367. - (void)btnDeleteModeTouched:(id)sender {
  368. CustomButton *btnDelete = (CustomButton *)sender;
  369. ItemSubModel *mode = btnDelete.value;
  370. [self.modes removeObject:mode];
  371. [self updateTableView];
  372. }
  373. - (void)btnDeleteDurationTouched:(id)sender {
  374. CustomButton *btnDelete = (CustomButton *)sender;
  375. ItemSubModel *dueDate = btnDelete.value;
  376. [self.durations removeObject:dueDate];
  377. [self updateTableView];
  378. }
  379. - (void)btnDeleteDeviceTouched:(id)sender {
  380. CustomButton *btnDelete = (CustomButton *)sender;
  381. ItemSubModel *pdevice = btnDelete.value;
  382. //선택 설정을 초기화
  383. [[JDFacade facade] setRadioButtonStatus:@NO object:pdevice];
  384. for (CmdClsValueModel *cmdclsValue in pdevice.cmdclsValueList) {
  385. cmdclsValue.isSelected = NO;
  386. }
  387. [self.pdevices removeObject:pdevice];
  388. [self updateTableView];
  389. }
  390. - (void)updateTableView {
  391. CGFloat height = (63 * 3) + 45;
  392. height = self.modes.count > 0 ? height + 86 : height;
  393. height = self.durations.count > 0 ? height + 86 : height;
  394. height = self.pdevices.count > 0 ? height + (86 * self.pdevices.count) : height;
  395. self.view.height = height;
  396. [_tableView reloadData];
  397. if ([self.parentViewController isKindOfClass:[RulesAddViewController class]]) {
  398. RulesAddViewController *rvc = (RulesAddViewController *)self.parentViewController;
  399. [rvc.tableView reloadData];
  400. }
  401. }
  402. #pragma mark - UI Events
  403. #pragma mark - MemoryWarning
  404. - (void)didReceiveMemoryWarning
  405. {
  406. [super didReceiveMemoryWarning];
  407. // Dispose of any resources that can be recreated.
  408. }
  409. @end