// // FLEXVariableEditorViewController.m // Flipboard // // Created by Ryan Olson on 5/16/14. // Copyright (c) 2020 FLEX Team. All rights reserved. // #import "FLEXColor.h" #import "FLEXVariableEditorViewController.h" #import "FLEXFieldEditorView.h" #import "FLEXRuntimeUtility.h" #import "FLEXUtility.h" #import "FLEXObjectExplorerFactory.h" #import "FLEXArgumentInputView.h" #import "FLEXArgumentInputViewFactory.h" #import "FLEXObjectExplorerViewController.h" #import "UIBarButtonItem+FLEX.h" #import "FLEXArgumentInputDateView.h" @interface FLEXVariableEditorViewController () @property (nonatomic) UIScrollView *scrollView; @end @implementation FLEXVariableEditorViewController #pragma mark - Initialization + (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)())onCommit { return [[self alloc] initWithTarget:target data:data commitHandler:onCommit]; } - (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)())onCommit { self = [super init]; if (self) { _target = target; _data = data; _commitHandler = onCommit; #if !TARGET_OS_TV [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil ]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil ]; #endif } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - UIViewController methods - (void)keyboardDidShow:(NSNotification *)notification { #if !TARGET_OS_TV CGRect keyboardRectInWindow = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGSize keyboardSize = [self.view convertRect:keyboardRectInWindow fromView:nil].size; UIEdgeInsets scrollInsets = self.scrollView.contentInset; scrollInsets.bottom = keyboardSize.height; self.scrollView.contentInset = scrollInsets; self.scrollView.scrollIndicatorInsets = scrollInsets; // Find the active input view and scroll to make sure it's visible. for (FLEXArgumentInputView *argumentInputView in self.fieldEditorView.argumentInputViews) { if (argumentInputView.inputViewIsFirstResponder) { CGRect scrollToVisibleRect = [self.scrollView convertRect:argumentInputView.bounds fromView:argumentInputView]; [self.scrollView scrollRectToVisible:scrollToVisibleRect animated:YES]; break; } } #endif } - (void)keyboardWillHide:(NSNotification *)notification { UIEdgeInsets scrollInsets = self.scrollView.contentInset; scrollInsets.bottom = 0.0; self.scrollView.contentInset = scrollInsets; self.scrollView.scrollIndicatorInsets = scrollInsets; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = FLEXColor.scrollViewBackgroundColor; self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; self.scrollView.backgroundColor = self.view.backgroundColor; self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.scrollView.delegate = self; [self.view addSubview:self.scrollView]; _fieldEditorView = [FLEXFieldEditorView new]; self.fieldEditorView.targetDescription = [NSString stringWithFormat:@"%@ %p", [self.target class], self.target]; [self.scrollView addSubview:self.fieldEditorView]; #if !TARGET_OS_TV _actionButton = [[UIBarButtonItem alloc] initWithTitle:@"Set" style:UIBarButtonItemStyleDone target:self action:@selector(actionButtonPressed:) ]; self.navigationController.toolbarHidden = NO; self.toolbarItems = @[UIBarButtonItem.flex_flexibleSpace, self.actionButton]; #else _actionButton = [UIButton buttonWithType:UIButtonTypeSystem]; [_actionButton setTitle:@"Set" forState:UIControlStateNormal]; [_actionButton addTarget:self action:@selector(actionButtonPressed:) forControlEvents:UIControlEventPrimaryActionTriggered]; _actionButton.frame = CGRectMake(500, 600, 200, 70); [self.view addSubview:_actionButton]; #endif } - (void)viewWillLayoutSubviews { CGSize constrainSize = CGSizeMake(self.scrollView.bounds.size.width, CGFLOAT_MAX); CGSize fieldEditorSize = [self.fieldEditorView sizeThatFits:constrainSize]; self.fieldEditorView.frame = CGRectMake(0, 0, fieldEditorSize.width, fieldEditorSize.height); #if TARGET_OS_TV CGRect actionFrame = _actionButton.frame; CGRect fieldEditorFrame = self.fieldEditorView.frame; CGFloat buttonOffset = (fieldEditorFrame.origin.y + fieldEditorFrame.size.height) + (130 + 67); actionFrame.origin.y = buttonOffset; _actionButton.frame = actionFrame; #endif self.scrollView.contentSize = fieldEditorSize; } #pragma mark - Public - (FLEXArgumentInputView *)firstInputView { return [self.fieldEditorView argumentInputViews].firstObject; } - (void)actionButtonPressed:(id)sender { // Subclasses can override [self.fieldEditorView endEditing:YES]; if (_commitHandler) { _commitHandler(); } } - (void)exploreObjectOrPopViewController:(id)objectOrNil { if (objectOrNil) { // For non-nil (or void) return types, push an explorer view controller to display the object FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:objectOrNil]; [self.navigationController pushViewController:explorerViewController animated:YES]; } else { // If we didn't get a returned object but the method call succeeded, // pop this view controller off the stack to indicate that the call went through. [self.navigationController popViewControllerAnimated:YES]; } } @end