FLEXVariableEditorViewController.m 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // FLEXVariableEditorViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 5/16/14.
  6. // Copyright (c) 2020 FLEX Team. All rights reserved.
  7. //
  8. #import "FLEXColor.h"
  9. #import "FLEXVariableEditorViewController.h"
  10. #import "FLEXFieldEditorView.h"
  11. #import "FLEXRuntimeUtility.h"
  12. #import "FLEXUtility.h"
  13. #import "FLEXObjectExplorerFactory.h"
  14. #import "FLEXArgumentInputView.h"
  15. #import "FLEXArgumentInputViewFactory.h"
  16. #import "FLEXObjectExplorerViewController.h"
  17. #import "UIBarButtonItem+FLEX.h"
  18. #import "FLEXArgumentInputDateView.h"
  19. @interface FLEXVariableEditorViewController () <UIScrollViewDelegate>
  20. @property (nonatomic) UIScrollView *scrollView;
  21. @end
  22. @implementation FLEXVariableEditorViewController
  23. #pragma mark - Initialization
  24. + (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)())onCommit {
  25. return [[self alloc] initWithTarget:target data:data commitHandler:onCommit];
  26. }
  27. - (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)())onCommit {
  28. self = [super init];
  29. if (self) {
  30. _target = target;
  31. _data = data;
  32. _commitHandler = onCommit;
  33. #if !TARGET_OS_TV
  34. [NSNotificationCenter.defaultCenter
  35. addObserver:self selector:@selector(keyboardDidShow:)
  36. name:UIKeyboardDidShowNotification object:nil
  37. ];
  38. [NSNotificationCenter.defaultCenter
  39. addObserver:self selector:@selector(keyboardWillHide:)
  40. name:UIKeyboardWillHideNotification object:nil
  41. ];
  42. #endif
  43. }
  44. return self;
  45. }
  46. - (void)dealloc {
  47. [NSNotificationCenter.defaultCenter removeObserver:self];
  48. }
  49. #pragma mark - UIViewController methods
  50. - (void)keyboardDidShow:(NSNotification *)notification {
  51. #if !TARGET_OS_TV
  52. CGRect keyboardRectInWindow = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
  53. CGSize keyboardSize = [self.view convertRect:keyboardRectInWindow fromView:nil].size;
  54. UIEdgeInsets scrollInsets = self.scrollView.contentInset;
  55. scrollInsets.bottom = keyboardSize.height;
  56. self.scrollView.contentInset = scrollInsets;
  57. self.scrollView.scrollIndicatorInsets = scrollInsets;
  58. // Find the active input view and scroll to make sure it's visible.
  59. for (FLEXArgumentInputView *argumentInputView in self.fieldEditorView.argumentInputViews) {
  60. if (argumentInputView.inputViewIsFirstResponder) {
  61. CGRect scrollToVisibleRect = [self.scrollView convertRect:argumentInputView.bounds fromView:argumentInputView];
  62. [self.scrollView scrollRectToVisible:scrollToVisibleRect animated:YES];
  63. break;
  64. }
  65. }
  66. #endif
  67. }
  68. - (void)keyboardWillHide:(NSNotification *)notification {
  69. UIEdgeInsets scrollInsets = self.scrollView.contentInset;
  70. scrollInsets.bottom = 0.0;
  71. self.scrollView.contentInset = scrollInsets;
  72. self.scrollView.scrollIndicatorInsets = scrollInsets;
  73. }
  74. - (void)viewDidLoad {
  75. [super viewDidLoad];
  76. self.view.backgroundColor = FLEXColor.scrollViewBackgroundColor;
  77. self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
  78. self.scrollView.backgroundColor = self.view.backgroundColor;
  79. self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  80. self.scrollView.delegate = self;
  81. [self.view addSubview:self.scrollView];
  82. _fieldEditorView = [FLEXFieldEditorView new];
  83. self.fieldEditorView.targetDescription = [NSString stringWithFormat:@"%@ %p", [self.target class], self.target];
  84. [self.scrollView addSubview:self.fieldEditorView];
  85. #if !TARGET_OS_TV
  86. _actionButton = [[UIBarButtonItem alloc]
  87. initWithTitle:@"Set"
  88. style:UIBarButtonItemStyleDone
  89. target:self
  90. action:@selector(actionButtonPressed:)
  91. ];
  92. self.navigationController.toolbarHidden = NO;
  93. self.toolbarItems = @[UIBarButtonItem.flex_flexibleSpace, self.actionButton];
  94. #else
  95. _actionButton = [UIButton buttonWithType:UIButtonTypeSystem];
  96. [_actionButton setTitle:@"Set" forState:UIControlStateNormal];
  97. [_actionButton addTarget:self action:@selector(actionButtonPressed:) forControlEvents:UIControlEventPrimaryActionTriggered];
  98. _actionButton.frame = CGRectMake(500, 600, 200, 70);
  99. [self.view addSubview:_actionButton];
  100. #endif
  101. }
  102. - (void)viewWillLayoutSubviews {
  103. CGSize constrainSize = CGSizeMake(self.scrollView.bounds.size.width, CGFLOAT_MAX);
  104. CGSize fieldEditorSize = [self.fieldEditorView sizeThatFits:constrainSize];
  105. self.fieldEditorView.frame = CGRectMake(0, 0, fieldEditorSize.width, fieldEditorSize.height);
  106. #if TARGET_OS_TV
  107. CGRect actionFrame = _actionButton.frame;
  108. CGRect fieldEditorFrame = self.fieldEditorView.frame;
  109. CGFloat buttonOffset = (fieldEditorFrame.origin.y + fieldEditorFrame.size.height) + (130 + 67);
  110. actionFrame.origin.y = buttonOffset;
  111. _actionButton.frame = actionFrame;
  112. #endif
  113. self.scrollView.contentSize = fieldEditorSize;
  114. }
  115. #pragma mark - Public
  116. - (FLEXArgumentInputView *)firstInputView {
  117. return [self.fieldEditorView argumentInputViews].firstObject;
  118. }
  119. - (void)actionButtonPressed:(id)sender {
  120. // Subclasses can override
  121. [self.fieldEditorView endEditing:YES];
  122. if (_commitHandler) {
  123. _commitHandler();
  124. }
  125. }
  126. - (void)exploreObjectOrPopViewController:(id)objectOrNil {
  127. if (objectOrNil) {
  128. // For non-nil (or void) return types, push an explorer view controller to display the object
  129. FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:objectOrNil];
  130. [self.navigationController pushViewController:explorerViewController animated:YES];
  131. } else {
  132. // If we didn't get a returned object but the method call succeeded,
  133. // pop this view controller off the stack to indicate that the call went through.
  134. [self.navigationController popViewControllerAnimated:YES];
  135. }
  136. }
  137. @end